Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a $text search perform a partial match

I'm very confused by this behavior. It seems inconsistent and strange, especially since I've read that Mongo isn't supposed to support partial search terms in full text search. I'm using version 3.4.7 of Mongo DB Community Server. I'm doing these tests from the Mongo shell.

So, I have a Mongo DB collection with a text index assigned. I created the index like this:

db.submissions.createIndex({"$**":"text"})

There is a document in this collection that contains these two values:

"Craig"

"Dr. Bob".

My goal is to do a text search for a document that has multiple matching terms in it.

So, here are tests I've run, and their inconsistent output:

SINGLE TERM, COMPLETE

db.submissions.find({"$text":{"$search":"\"Craig\""}})

Result: Gets me the document with this value in it.

SINGLE TERM, PARTIAL

db.submissions.find({"$text":{"$search":"\"Crai\""}})

Result: Returns nothing, because this partial search term doesn't exactly match anything in the document.

MULTIPLE TERMS, COMPLETE

db.submissions.find({"$text":{"$search":"\"Craig\" \"Dr. Bob\""}})

Result: Returns the document with both of these terms in it.

MULTIPLE TERMS, ONE PARTIAL

db.submissions.find({"$text":{"$search":"\"Craig\" \"Dr. Bo\""}})

Result: Returns the document with both terms in it, despite the fact that one term is partial. There is nothing in the document that matches "Dr. Bo"

MULTIPLE TERMS, BOTH PARTIAL

db.submissions.find({"$text":{"$search":"\"Crai\" \"Dr. Bo\""}})

Result: Returns the document with both terms in it, despite the fact that both terms are partial and incomplete. There is nothing in the document that matches either "Crai" or "Dr. Bo".

Question

So, it all boils down to: why? Why is it, when I do a text search with a partial term with only a single value, nothing gets returned. When I do a text search with two partial terms, I get the matching result? It just seems so strange and inconsistent.

like image 670
craigmiller160 Avatar asked Sep 18 '17 21:09

craigmiller160


People also ask

How do I do a partial search in MongoDB?

In MongoDB, we can search the text by using the $text query operator and it is used to perform text searches on a collection with a text index. It provides text indexes to support text search queries on string content.

What is partial search?

A partial term search refers to queries consisting of term fragments, where instead of a whole term, you might have just the beginning, middle, or end of term (sometimes referred to as prefix, infix, or suffix queries).

How do I use wildcard search in MongoDB?

Create a Wildcard Index on All Fields With this wildcard index, MongoDB indexes all fields for each document in the collection. If a given field is a nested document or array, the wildcard index recurses into the document/array and stores the value for all fields in the document/array.

How would you implement a search query in MongoDB?

Use the $text query operator to perform text searches on a collection with a text index. $text will tokenize the search string using whitespace and most punctuation as delimiters, and perform a logical OR of all such tokens in the search string.


1 Answers

MongoDB $text searches do not support partial matching. MongoDB allows text search queries on string content with support for case insensitivity, delimiters, stop words and stemming. And the terms in your search string are, by default, OR'ed.

Taking your (very useful :) examples one by one:

SINGLE TERM, PARTIAL

// returns nothing because there is no world word with the value `Crai` in your
// text index and there is no whole word for which `Crai` is a recognised stem
db.submissions.find({"$text":{"$search":"\"Crai\""}})

MULTIPLE TERMS, COMPLETE

// returns the document because it contains all of these words
// note in the text index Dr. Bob is not a single entry since "." is a delimiter
db.submissions.find({"$text":{"$search":"\"Craig\" \"Dr. Bob\""}})

MULTIPLE TERMS, ONE PARTIAL

// returns the document because it contains the whole word "Craig" and it 
// contains the whole word "Dr" 
db.submissions.find({"$text":{"$search":"\"Craig\" \"Dr. Bo\""}})

MULTIPLE TERMS, BOTH PARTIAL

// returns the document because it contains the whole word "Dr"
db.submissions.find({"$text":{"$search":"\"Crai\" \"Dr. Bo\""}})

Bear in mind that the $search string is ...

A string of terms that MongoDB parses and uses to query the text index. MongoDB performs a logical OR search of the terms unless specified as a phrase.

So, if at least one term in your $search string matches then MongoDB matches that document.

To verify this behaviour, if you edit your document changing Dr. Bob to DrBob then the following queries will return no documents:

db.submissions.find({"$text":{"$search":"\"Craig\" \"Dr. Bo\""}})
db.submissions.find({"$text":{"$search":"\"Crai\" \"Dr. Bo\""}})

These now return no matches because Dr is no longer a whole word in your text index because it is not followed by the . delimiter.

like image 85
glytching Avatar answered Sep 23 '22 14:09

glytching