Search Text
On this page
Overview
In this guide, you can learn how to run a text search.
Important
MongoDB text search is different than Atlas Search.
Sample Data
The examples in this guide use the following Dish
struct as a model for documents
in the menu
collection:
type Dish struct { Name string Description string }
To run the examples in this guide, load the sample data into the
db.menu
collection with the following
snippet:
coll := client.Database("db").Collection("menu") docs := []interface{}{ Dish{Name: "Shepherd’s Pie", Description: "A vegetarian take on the classic dish that uses lentils as a base. Serves 2."}, Dish{Name: "Green Curry", Description: "A flavorful Thai curry, made vegetarian with fried tofu. Vegetarian and vegan friendly."}, Dish{Name: "Herbed Whole Branzino", Description: "Grilled whole fish stuffed with herbs and pomegranate seeds. Serves 3-4."}, Dish{Name: "Kale Tabbouleh", Description: "A bright, herb-based salad. A perfect starter for vegetarians and vegans."}, Dish{Name: "Garlic Butter Trout", Description: "Baked trout seasoned with garlic, lemon, dill, and, of course, butter. Serves 2."}, } result, err := coll.InsertMany(context.TODO(), docs)
Each document contains the name
and description
of a dish on a
restaurant's menu.
Tip
Non-existent Databases and Collections
If the necessary database and collection don't exist when you perform a write operation, the server implicitly creates them.
Text Index
You must create a text index before running a text search. A text index specifies the string or string array field on which to run a text search.
The examples in the following sections run text searches on the
description
field of documents in the menu
collection. To enable text searches on
the description
field, create a text index with the following snippet:
model := mongo.IndexModel{Keys: bson.D{{"description", "text"}}} name, err := coll.Indexes().CreateOne(context.TODO(), model) if err != nil { panic(err) } fmt.Println("Name of index created: " + name)
Text Search
A text search retrieves documents that contain a term or a phrase in the text indexed fields. A term is a sequence of characters that excludes whitespace characters. A phrase is a sequence of terms with any number of whitespace characters.
To perform a text search, use the $text
evaluation query operator,
followed by the $search
field in your query filter. The $text
operator
performs a text search on the text indexed fields. The $search
field
specifies the text to search in the text indexed fields.
Query filters for text searches use the following format:
filter := bson.D{{"$text", bson.D{{"$search", "<text to search>"}}}}
Search by a Term
To search for a term, specify the term as a string in your query filter. To search for multiple terms, separate each term with spaces in the string.
Note
When searching for multiple terms, the Find()
method returns
documents with at least one of the terms in text indexed fields.
Example
The following example runs a text search for descriptions that contain the term "herb":
filter := bson.D{{"$text", bson.D{{"$search", "herb"}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := json.Marshal(result) fmt.Println(string(res)) }
Tip
Although the search term was "herb", the method also matches descriptions containing "herbs" because a MongoDB text index uses suffix stemming to match similar words. To learn more about how MongoDB matches terms, see Index Entries.
Search by a Phrase
To search for a phrase, specify the phrase with escaped quotes as a
string in your query filter. If you don't add escaped quotes around the
phrase, the Find()
method runs a term search.
Tip
Escaped quotes are a backslash character followed by a double quote character.
Example
The following example runs a text search for descriptions that contain the phrase "serves 2":
filter := bson.D{{"$text", bson.D{{"$search", "\"serves 2\""}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := json.Marshal(result) fmt.Println(string(res)) }
Search with Terms Excluded
For each term or phrase you want to exclude from your text search, specify the term or phrase prefixed with a minus sign as a string in your query filter.
Important
You must search for at least one term if you want to exclude
terms from your search. If you don't search for any terms, the
Find()
method doesn't return any documents.
Example
The following example runs a text search for descriptions that contain the term "vegan", but do not contain the term "tofu":
filter := bson.D{{"$text", bson.D{{"$search", "vegan -tofu"}}}} cursor, err := coll.Find(context.TODO(), filter) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := json.Marshal(result) fmt.Println(string(res)) }
Sort by Relevance
A text search assigns a numerical text score to indicate how closely
each result matches the string in your query filter. To reveal the text
score in your output, use a projection to retrieve the textScore
metadata. You can sort the text score in descending order by specifying
a sort on the textScore
metadata.
Example
The following example performs the following actions:
Runs a text search for descriptions that contain the term "vegetarian"
Sorts the results in descending order based on their text score
Includes only the
name
andscore
fields in the final output document
filter := bson.D{{"$text", bson.D{{"$search", "vegetarian"}}}} sort := bson.D{{"score", bson.D{{"$meta", "textScore"}}}} projection := bson.D{{"name", 1}, {"score", bson.D{{"$meta", "textScore"}}}, {"_id", 0}} opts := options.Find().SetSort(sort).SetProjection(projection) cursor, err := coll.Find(context.TODO(), filter, opts) if err != nil { panic(err) } var results []bson.D if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { fmt.Println(result) }
Aggregation
You can also include the $text
evaluation query operator in the
$match stage to
perform a text search in an aggregation pipeline.
Match a Search Term
The following example runs a text search for descriptions that contain the term "herb":
matchStage := bson.D{{"$match", bson.D{{"$text", bson.D{{"$search", "herb"}}}}}} cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{matchStage}) if err != nil { panic(err) } var results []Dish if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { res, _ := json.Marshal(result) fmt.Println(string(res)) }
Sort by Relevance
The following example performs the following actions:
Runs a text search for descriptions that contain the term "vegetarian"
Sorts the results in descending order based on their text score
Includes only the
name
andscore
fields in the final output document
matchStage := bson.D{{"$match", bson.D{{"$text", bson.D{{"$search", "vegetarian"}}}}}} sortStage := bson.D{{"$sort", bson.D{{"score", bson.D{{ "$meta", "textScore" }}}}}} projectStage := bson.D{{"$project", bson.D{{"name", 1}, {"score", bson.D{{ "$meta", "textScore" }}}, {"_id", 0}}}} cursor, err := coll.Aggregate(context.TODO(), mongo.Pipeline{matchStage, sortStage, projectStage}) if err != nil { panic(err) } var results []bson.D if err = cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { fmt.Println(result) }
Additional Information
To learn more about the operations mentioned, see the following guides:
API Documentation
To learn more about any of the methods or types discussed in this guide, see the following API Documentation: