3

I have a collection with following docs:

{
    "_id" : ObjectId("5ad609a2ac1a8b644180936a"),
    "content" : "Coffee and cakes..."
},
{
    "_id" : ObjectId("5ad609baac1a8b644180936b"),
    "content" : "coffee shop..."
}

Result of the text search query:

find({ $text: { $search: "\"coffee shop\" cakes" } })

returns only second document, but I am expecting both docs. What is the problem?

glytching
  • 44,936
  • 9
  • 114
  • 120

2 Answers2

4

This ...

find({ $text: { $search: "coffee shop cakes" } })

... will search for any document having a content attribute which contains any one of "coffee" or "shop" or "cake"

But this ...

find({ $text: { $search: "\"coffee shop\" cakes" } })

... will search for any document having a content attribute which contains the phrase "coffee shop".

I think you are expecting both of the above behaviours when you submit a phrase ("coffee shop") and an extra search value ("cakes"). However, this is not how MongoDB treats a combination of phrase and additional terms.

From the docs:

If the $search string includes a phrase and individual terms, text search will only match the documents that include the phrase.

Based on these docs the query "\"coffee shop\" cakes" will be evaluated as:

"coffee shop" AND ("cakes" or "coffee" or "shop")

This correctly matches only the second document.

Note: the text index docs contradict this, according to those docs the query "\"coffee shop\" cakes" will be evaluated as: "coffee shop" OR "cakes" but the behaviour you are observing is consistent with the $text operator docs quoted above.

Thanks to @RahulRaj for raising this issue with MongoDB, their response confirms that the docs are incorrect:

As you correctly note, there is an inconsistency in the documentation between these two pages. We're tracking this fix to the documentation in DOCS-10382.

https://docs.mongodb.com/manual/reference/operator/query/text/#phrases correctly describes the current implementation of this feature.

Community
  • 1
  • 1
glytching
  • 44,936
  • 9
  • 114
  • 120
  • https://docs.mongodb.com/manual/text-search/ As per the docs, it says it returns **all documents** containing “coffee shop” **OR** “cakes”. So it should return both documents. why it isnt happening? I guess that's what OP is concerned for. Hope you understood the point mentioned on mongo docs. – Rahul Raj Apr 17 '18 at 16:24
  • The [text index docs](https://docs.mongodb.com/manual/text-search/#exact-phrase) are contradicted by the [`$text` operator docs](https://docs.mongodb.com/manual/reference/operator/query/text/#phrases) but the actual behaviour (as observed by the OP) is supported by the quote from the `$text` operator docs which I included in this answer. – glytching Apr 17 '18 at 16:33
  • Got that, but Its mentioned **OR** in text index docs(which is exactly the same case here unless OP doesnt have text index), not an **AND**. I created text index and tested for the same and getting the same result as OP. – Rahul Raj Apr 17 '18 at 16:36
  • The docs say OR in [one place](https://docs.mongodb.com/manual/text-search/#exact-phrase) and say AND in [another place](https://docs.mongodb.com/manual/reference/operator/query/text/#phrases). The actual behaviour (observed by me on v3.4.7 and by the OP on whatever version being run there) is: AND. This suggests that the `$text` operator docs are the correct ones. – glytching Apr 17 '18 at 16:50
  • **AND** is not OP's result right? if **AND** is the chosen search form, then result would be nil since there are no content with both `coffee shop` and `cakes` at one place. The case here is OP got a result which not **OR** and at the same time not an **AND**. I created a jira request to hear back from mongo team about this. – Rahul Raj Apr 17 '18 at 16:54
  • The AND branch causes this query `"\"coffee shop\" cakes"` to be evaluated as `"coffee shop" AND ("cakes" or "coffee" or "shop")` (taken from [the docs](https://docs.mongodb.com/manual/reference/operator/query/text/#phrases)). – glytching Apr 17 '18 at 16:57
  • Thanks for the example. So now the question is why did they mention **OR** in the other place and where can it be valid? – Rahul Raj Apr 17 '18 at 17:00
  • Thanks @RahulRaj, I have updated the answer with the conclusion from that JIRA. – glytching Apr 18 '18 at 06:57
0

Try using regex

db.collectionName.find( { content: { $regex: /^coffee/i} } );


/i will be for ignoring case


Help link : https://docs.mongodb.com/manual/reference/operator/query/regex/#examples

Dev
  • 11
  • 1
  • 2
    I think the question was focused on use of a text index and the `$text` operator. The `$regex` operator _could_ be used to apply a similar query but that would not answer the OP's question about **why** a text search did not return both documents. – glytching Apr 17 '18 at 16:22