Docs Menu

Docs HomeDevelop ApplicationsMongoDB DriversGo Driver

Search Text

On this page

  • Overview
  • Sample Data
  • Text Index
  • Text Search
  • Search by a Term
  • Search by a Phrase
  • Search with Terms Excluded
  • Sort by Relevance
  • Aggregation
  • Match a Search Term
  • Sort by Relevance
  • Additional Information
  • API Documentation

In this guide, you can learn how to run a text search.

Important

MongoDB text search is different than Atlas Search.

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

Nonexistent Databases and Collections

If the necessary database and collection don't exist when you perform a write operation, the server implicitly creates them.

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)

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>"}}}}

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.

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, _ := bson.MarshalExtJSON(result, false, false)
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.

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.

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, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}

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.

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, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}

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.

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 and score 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 {
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}

You can also include the $text evaluation query operator in the $match stage to perform a text search in an aggregation pipeline.

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, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}

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 and score 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 {
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}

To learn more about the operations mentioned, see the following guides:

To learn more about any of the methods or types discussed in this guide, see the following API Documentation:

←  Specify Which Fields to ReturnMonitor Data Changes →