Reputation: 6158
I am using mongo text search in my application.
db.test.createIndex(
{
title: 'text',
description: 'text'
},
{
name: "TextIndex",
weights: {
title: 10,
description: 1
}
}
)
title : 10
description : 1
db.test.insert(
[
{ _id: 1, title: "agent de production", description: "production or agent"},
{ _id: 2, title: "agent test production", description: "agent" },
{ _id: 3, title: "production agent", "description" : "production"},
{ _id: 4, title: "agent", "description" : "production"},
{ _id: 5, title: "test", "description" : "production example agent"},
]
)
So if I search "agent production"
Result should be
[
{ _id: 1, title: "agent de production", description: "production or agent"},
{ _id: 2, title: "agent test production", description: "agent" },
{ _id: 3, title: "production agent", "description" : "production"},
{ _id: 5, title: "test", "description" : "production example agent"},
]
db.test.find({"$text" : {"$search" : "\"agent production\""}}); Query result does not match with the expected result.
Result : Nil
Query phrase : db.test.find({"$text" : {"$search" : "\"agent\" \"production\""}})
Result :
{ "_id" : 5, "title" : "test", "description" : "production example agent" }
{ "_id" : 1, "title" : "agent de production", "description" : "production or agent" }
{ "_id" : 3, "title" : "production agent", "description" : "production" }
{ "_id" : 2, "title" : "agent test production", "description" : "agent" }
{ "_id" : 4, "title" : "agent", "description" : "production" }
Any suggestion will be grateful.
Upvotes: 1
Views: 376
Reputation: 2557
Let's review how the $search string in the $text query works. If a phrase is given, as in "$search": "\"agent production\""
, only documents with indexed fields matching the phrase receive a non-zero score. That explains why no results were found in this case. However specifying "$search": "\"production agent\""
would match the document with _id: 3
. If individual words/terms are given, as in "$search": "\"agent\" \"production\""
, any document with indexed fields matching any of the terms receive a score. This explains why document with _id: 4
is returned since it has the individual terms not necessarily both terms in a single field, as you have shown in your desired result.
To enforce that both search terms are included in a single field, you need to add additional clauses to the query. You can perform the text search for scoring the documents and filter them further using regex as in:
db.test.find( { $and: [ { "$text": { "$search": "\"agent\" \"production\"" } },
{ $or: [
{ $and: [ { title: /agent/i }, { title: /production/i } ] },
{ $and: [ { description: /agent/i }, { description: /production/i } ] }
] }
] }, { score: { $meta: "textScore" } } ).sort( { score: { $meta: "textScore" } } )
Note that the textScore is added because the documents are not sorted based on score by default.
Upvotes: 2