I want to limit text scores using the $gt operator.
Using the find function, I can sort the text scores according to the text similarity status from largest to smallest. I can get the cursor with the highest score by putting a limit of 1 on the rank.
deneme = user.find(
{ '$text': { '$search': "dogan can" } },
{ 'score': { '$meta': "textScore" }})
deneme_sort = deneme.sort([('score', {'$meta': 'textScore'})]).limit(1)
But I don't want the ones whose text score is below the value I gave, to be listed.
For example, I don't want text scores below 1.5 to appear in the list. I'm trying to use the '$gt' operator for this but I'm getting an error.
deneme = user.find(
{ '$text': { '$search': "dogan can" } },
{ 'score': { '$meta': "textScore"}}, {'score': { '$gt': 1.5 } })
TypeError: skip must be an instance of int
it gives this error because the find function can only take two values.
I'm trying to query using the '$and' operator. This time it does not recognize the '$meta' operator. Or the '$gt' operator must take two values.
deneme = user.find({ '$text': { '$search': "dogan can" }} ,
{'$and':[{ 'score': { '$meta': "textScore" }},{'score': { '$gt': 1.5 }}]})
doc = []
for doc in deneme:
print(doc)
Expression $gt takes exactly 2 arguments. 1 were passed in., full error: {'ok': 0.0, 'errmsg': 'Expression $gt takes exactly 2 arguments. 1 were passed in.', 'code': 16020, 'codeName': 'Location16020'}
I just started learning mongodb. Can you help me?
CodePudding user response:
I think what you're requesting is documented here. In short - you will need to use the aggregation framework so that you can have 3 stages to accomplish each of the following:
- Perform the initial
$text
searching in a$match
stage - Persist the text score as part of the document via an
$addFields
stage - Use an additional
$match
stage to perform the$gt
filtering against that new score field.
Given a collection with the following documents:
test> db.foo.find()
[
{ _id: 1, key: 'dogan can' },
{ _id: 2, key: 'dogan' },
{ _id: 3, key: 'can' },
{ _id: 4, key: 'abc' }
]
A text search against dogan can
will return the first three documents:
test> db.foo.aggregate([ { $match: { $text: { $search: "dogan can" } } },{$addFields:{score:{$meta:'textScore'}}}])
[
{ _id: 3, key: 'can', score: 1.1 },
{ _id: 1, key: 'dogan can', score: 1.5 },
{ _id: 2, key: 'dogan', score: 1.1 }
]
Appending the final $match
(using a filter of 1.2
), only one of the documents is returned:
test> db.foo.aggregate([ { $match: { $text: { $search: "dogan can" } } },{$addFields:{score:{$meta:'textScore'}}},{$match:{score:{$gt:1.2}}}])
[
{ _id: 1, key: 'dogan can', score: 1.5 }
]
If desired, you can of course include a $sort
stage on the score as well.