When MongoDB returns text search results, it assigns a score to each returned document. The score indicates the relevance of the document to a given search query. You can sort returned documents by score to have the most relevant documents appear first in the result set.
If you have a compound index with multiple text index keys, you can specify different weights for each indexed field. The weight of an indexed field indicates the significance of the field relative to the other indexed fields, with higher weights resulting in higher text search scores.
For example, you can emphasize search matches on a title field if
you know users are likely to search for titles, or if title contains
more relevant search terms compared to other document fields.
The default weight for indexed is 1 for the indexed fields. To adjust
the weights for the indexed fields, include the weights option in the
db.collection.createIndex() method, as seen in this example:
db.<collection>.createIndex( { <field1>: "text", <field2>: "text", ... }, { weights: { <field1>: <weight>, <field2>: <weight>, ... }, name: <indexName> } )
Important
If you change the weights in your index after it is created, MongoDB needs to reindex the collection. Reindexing can negatively impact performance, especially on large collections. For more information, see Index Builds on Populated Collections.
About this Task
You have a blog collection that contains documents for individual
blog posts. Each document contains:
The content of the post.
The topic that the post covers.
A list of keywords related to the post.
You want to create a text index so users can perform text searches on blog posts. Your application supports searches on content, topics, and keywords.
You want to prioritize matches on the content field over other
document fields. Use index weights to assign greater importance to
matches on content and sort query results so content matches
appear first.
Before You Begin
Create a blog collection with the following documents:
db.blog.insertMany( [ { _id: 1, content: "This morning I had a cup of coffee.", about: "beverage", keywords: [ "coffee" ] }, { _id: 2, content: "Who likes chocolate ice cream for dessert?", about: "food", keywords: [ "poll" ] }, { _id: 3, content: "My favorite flavors are strawberry and coffee", about: "ice cream", keywords: [ "food", "dessert" ] } ] )
Procedure
Create a text index with different weights for each indexed field:
db.blog.createIndex( { content: "text", keywords: "text", about: "text" }, { weights: { content: 10, keywords: 5 }, name: "BlogTextIndex" } )
The text index has the following fields and weights:
contenthas a weight of 10.keywordshas a weight of 5.abouthas the default weight of 1.
These weights indicate the relative significance of the indexed fields to each other.
Results
The following examples show how different weights for indexed fields
affect result scores. Each example sorts results based on the
textScore of each document. To access documents' textScore
attributes, use the $meta operator.
Matches in content and about Fields
The following query searches documents in the blog collection for
the string ice cream:
db.blog.find( { $text: { $search: "ice cream" } }, { score: { $meta: "textScore" } } ).sort( { score: { $meta: "textScore" } } )
Output:
[ { _id: 2, content: 'Who likes chocolate ice cream for dessert?', about: 'food', keywords: [ 'food', 'poll' ], score: 12 }, { _id: 3, content: 'My favorite flavors are strawberry and coffee', about: 'ice cream', keywords: [ 'food', 'dessert' ], score: 1.5 } ]
The search string ice cream matches:
The
contentfield in the document with_id: 2.The
aboutfield in the document with_id: 3.
A term match in the content field has 10 times the impact
(10:1 weight) as a term match in the keywords field.
Matches in keywords and about Fields
The following query searches documents in the blog collection for
the string food:
db.blog.find( { $text: { $search: "food" } }, { score: { $meta: "textScore" } } ).sort( { score: { $meta: "textScore" } } )
Output:
[ { _id: 3, content: 'My favorite flavors are strawberry and coffee', about: 'ice cream', keywords: [ 'food', 'dessert' ], score: 5.5 }, { _id: 2, content: "Who likes chocolate ice cream for dessert?", about: 'food', keywords: [ 'poll' ], score: 1.1 } ]
The search string food matches:
The
keywordsfield in the document with_id: 3.The
aboutfield in the document with_id: 2.
A term match in the keywords field has 5 times the impact
(5:1 weight) as a term match in the about field.
Multiple Matches in a Single Document
The following query searches documents in the blog collection for
the string coffee:
db.blog.find( { $text: { $search: "coffee" } }, { score: { $meta: "textScore" } } ).sort( { score: { $meta: "textScore" } } )
Output:
[ { _id: 1, content: 'This morning I had a cup of coffee.', about: 'beverage', keywords: [ 'coffee' ], score: 11.666666666666666 }, { _id: 3, content: 'My favorite cake flavors are strawberry and coffee', about: 'ice cream', keywords: [ 'food', 'dessert' ], score: 6 } ]
The search string coffee matches:
The
contentandkeywordsfields in the document with_id: 1.The
contentfield in the document with_id: 3.
To calculate the score when a search string matches multiple fields,
MongoDB multiplies the number of matches by the weight for the
corresponding field and sums the results.
Learn More
To learn more about text search in MongoDB, see:
Note
MongoDB Search
For data hosted on MongoDB,
MongoDB Search provides more robust custom
scoring than text indexes. To learn more, see the MongoDB Search
Scoring documentation.