Django Choice Queries with annotate - python

I am stucked in django annotate query.
here is certain Model I have been working.
class Claim(model.Model)
CLAIMS_STATUS_CHOICES = (
(2, PROCESSING),
(1, ACCEPTED),
(0, REJECTED)
)
status = models.CharField(max_length=10,choice=CLAIMS_STATUS_CHOICES)
problem is I don't want to annotate processing choice but I just want to get individual status count of accepted and rejected.
Here is what I tried.
claim = Claim.objects.filter(Q(status=1) | Q(status=0))
total_status_count = claim.count()
status_counts = Claim.objects.filter(Q(status=1) |Q(status=0)).annotate(count=Count('status')).values('count', 'status')
but I am getting multiple rejected and accepted queries
this is what I got as op
[
{
"total_claims": 3,
"status_count": [
{
"status": "1",
"count": 1
},
{
"status": "0",
"count": 1
},
{
"status": "1",
"count": 1
}
]
}
]
what I wanted
[
{
"total_claims": 3,
"status_count": [
{
"status": "1",
"count": 2
},
{
"status": "0",
"count": 1
}
]
}
]
Any help regarding this?

Claim.objects.exclude(status=2).values('status').annotate(count=Count('status'))

I have done a similar task in my project, where I have to count the total completed and in progress projects. In my case, the scenario is, every project have a status.
In the project model, status is a choice field which have choices (uploaded, inprogress, inreview, and completed).
I'm posting the query here, maybe someone finds it helpful. In an API, write the following query:
from django.db.models import Count, Q
project_counts = Project.objects.filter(user=self.request.user).aggregate(
total=Count('id'),
inprogress=Count('id', Q(status=Project.ProjectStatus.IN_PROGRESS)),
completed=Count('id', Q(status=Project.ProjectStatus.COMPLETED)))
and then return the response like this.
return response.Response({
'total': project_counts['total'] | 0,
'inprogress': project_counts['inprogress'] | 0,
'completed': project_counts['completed'] | 0
})

Related

How to use the sum of two fields when searching for a document in MongoDB?

I have a collection of accounts and I am trying to find an account in which the targetAmount >= totalAmount + N
{
"_id": {
"$oid": "60d097b761484f6ad65b5305"
},
"targetAmount": 100,
"totalAmount": 0,
"highPriority": false,
"lastTimeUsed": 1624283088
}
Now I just select all accounts, iterate over them and check if the condition is met. But I'm trying to do this all in a query:
amount = 10
tasks = ProviderAccountTaskModel.objects(
__raw__={
'targetAmount': {
'$gte': {'$add': ['totalAmount', amount]}
}
}
).order_by('-highPriority', 'lastTimeUsed')
I have also tried using the $sum, but both options do not work.
Can't it be used when searching, or am I just going the wrong way?
You can use a $where. Just be aware it will be fairly slow (has to execute Javascript code on every record) so combine with indexed queries if you can.
db.getCollection('YourCollectionName').find( { $where: function() { return this.targetAmount > (this.totalAmount + 10) } })
or more compact way of doing it will be
db.getCollection('YourCollectionName').find( { $where: "this.targetAmount > this.totalAmount + 10" })
You have to use aggregation instead of the find command since self-referencing of documents in addition to arithmetic operations won't work on it.
Below is the aggregation command you are looking for. Convert it into motoengine equivalent command.
db.collection.aggregate([
{
"$match": {
"$expr": {
"$gte": [
"$targetAmount",
{
"$sum": [
"$totalAmount",
10
]
},
],
},
},
},
{
"$sort": {
"highPriority": -1,
"lastTimeUsed": 1,
},
},
])
Mongo Playground Sample Execution

How to get th content of a string inside a request response?

I was coding a webapp based on GPT-2 but it was not good so I decided to switch to official OpenAI GPT-3.
So I make that request:
response = openai.Completion.create(
engine="davinci",
prompt="Hello",
temperature=0.7,
max_tokens=64,
top_p=1,
frequency_penalty=0,
presence_penalty=0
)
And when I print the response I get this:
{
"choices": [
{
"finish_reason": "length",
"index": 0,
"logprobs": null,
"text": ", everyone, and welcome to the first installment of the new opening"
}
],
"created": 1624033807,
"id": "cmpl-3CBfb8yZAFEUIVXfZO90m77dgd9V4",
"model": "davinci:2020-05-03",
"object": "text_completion"
}
But I only want to print the text, so how can I do to print the "text" value in the response list.
Thank you in advance and have a good day.
Using the dict indexing by key, and the list indexing by index
x = {"choices": [{"finish_reason": "length",
"text": ", everyone, and welcome to the first installment of the new opening"}], }
text = x['choices'][0]['text']
print(text) # , everyone, and welcome to the first installment of the new opening
You can try print(response["choices"][0]["text"])
Hope this helps.
I think GPT-3 response structure has been changed, for reference, the response object looks this:
const response = await openai.createCompletion({
model: "text-davinci-002",
prompt: "Say this is a test",
temperature: 0,
max_tokens: 6,
});
// the response looks like the following
{
status: 200,
statusText: 'OK',
headers: {
},
config: {
},
request: <ref *1> ClientRequest {
},
data: {
id: 'cmpl-5zzyzqvh4Hmi5yyNL2LMI9ADkLBU0',
object: 'text_completion',
created: 1665457953,
model: 'text-davinci-002',
choices: [ [Object] ],
usage: { prompt_tokens: 5, completion_tokens: 6, total_tokens: 11 }
}
}
// choices can be accessed like this
var { choices } = { ...response.data }

how to generalise elastic search code for more than 3 skills

Presently my elastic search query can work up to 3 skills. How can I generalize this below-mentioned query for any number of skills
For quicker sollution, I duplicated the code for each skill.
def results(indexedfiles, query_skills_list):
if len(query_skills_list) == 3:
search_results = indexedfiles.search(
index="indexed_rem",
doc_type="rem1",
body={
"_source": ["Filename", "SkillsFound"],
"from": 0,
"size": 10,
"query": {
"bool": {
"must": [
{"match_phrase": {"SkillsFound": query_skills_list[0]}},
{"match_phrase": {"SkillsFound": query_skills_list[1]}},
{"match_phrase": {"SkillsFound": query_skills_list[2]}},
]
}
},
},
)
return search_results
How can I generalize this code for any number of skills?
Create your must clause list where your skills counter is SKILLS_COUNT.
must_query = [{'match_phrase': {'SkillsFound': query_skills_list[i]}} for i in range(SKILLS_COUNT)]
and set it in your code with 'must': must_query.

How to update value of a field within a document in Elasticsearch using python

I have this data stored in the Elasticsearch which is in this json format:
{
"qna": [
{
"qid": "1",
"question": [
"How to use the tool"
],
"answer": "Create and administer your questions Content Designer UI.",
"votes": "0"
},
{
"qid": "2",
"question": [
"How can I include attachements"
],
"answer": "Add an image attachment to the item using the Content Designer.",
"votes": "0"
}
]
}
Now I have written this code where when a question string is passed I am able to fetch the answer from Elasticsearch:
from elasticsearch import Elasticsearch
def search_es(question,index_name):
es = Elasticsearch([{'host': 'localhost', 'port': 9200}])
data = {
"query": {
"function_score":{
"query":{
"match": {
'question': question
}
},
"field_value_factor":{
"field":"votes",
"modifier":"log2p"
}
}
}
}
response = es.search(index=str(index_name).lower(), body=data)
for items in response['hits']['hits']:
score = items['_score']
answer = source['a']
score_answer.append([score,answer])
score_answer.sort(key=lambda x: int(x[0]), reverse=True)
# SELECT ONE ANSWER - TOP SCORED ANSWER
print(score_answer[0][1])
# CODE TO INCREASE VOTE OF THE SELECTED ANSWER
increase_vote(score_answer[0][1])
def increase_vote(answer):
# IMPLEMENT CODE HERE
As you can see the search_es() extracts and selects the top scored answer field. Now what I want to do is implement a function that will update the votes field associated with the selected answer and increase it by 1. I looked around and found few posts related to partial update of documents like this but am unable to figure out a way on how to update the field as described in my scenario?

Pymongo count elements collected out of all documents with key

I want to count all elements which occur in somekey in an MongoDB collection.
The current code looks at all elements in somekey as a whole.
from pymongo import Connection
con = Connection()
db = con.database
collection = db.collection
from bson.code import Code
reducer = Code("""
function(obj, prev){
prev.count++;
}
""")
from bson.son import SON
results = collection.group(key={"somekey":1}, condition={}, initial={"count": 0}, reduce=reducer)
for doc in results:
print doc
However, I want that it counts all elements which occur in any document with somekey.
Here is an anticipated example. The MongoDB has the following documents.
{ "_id" : 1, “somekey" : [“AB", “CD"], "someotherkey" : "X" }
{ "_id" : 2, “somekey" : [“AB", “XY”], "someotherkey" : "Y" }
The result should provide an by count ordered list with:
count: 2 "AB"
count: 1 "CD"
count: 1 "XY"
The .group() method will not work on elements that are arrays, and the closest similar thing would be mapReduce where you have more control over the emitted keys.
But really the better fit here is the aggregation framework. It is implemented in native code as does not use JavaScript interpreter processing as the other methods there do.
You wont be getting an "ordered list" from MongoDB responses, but you get a similar document result:
results = collection.aggregate([
# Unwind the array
{ "$unwind": "somekey" },
# Group the results and count
{ "$group": {
"_id": "$somekey",
"count": { "$sum": 1 }
}}
])
Gives you something like:
{ "_id": "AB", "count": 2 }
{ "_id": "CD", "count": 1 }
{ "_id": "XY", "count": 1 }

Categories