I have a MongoDB collection db.articles,it has 2 keys ,"title" and "abstract".I want to do text search on these two keys.For example, the search text is "physics",and I want all the documents whose "title" or "abstract" contains keyword "physics" is returned.But how to create the text index to meet my command is really confusing me:
Should I create two separate text indexes for both of them like this:
db.articles.ensureIndex({title:"text"})
db.articles.ensureIndex({abstract:"text"})
or
should I create a index in a single command and give the equal weight:
db.articles.ensureIndex(
{
title: "text",
abstract: "text",
},
{
weights: {
title: 1,
abstract:1,
},
name: "TextIndex"
}
)
I am already get used to the operation find(),whose query granularity is key,that is ,you should indicate the key you want to query on.But for text index, it seems like a document granularity,you cannot indicate the key you want to query on , instead ,you can only indicate the document name.So , what can I do if I want to do text search on a special key?
2 Answers 2
So, no need to test as it turns out, I just remembered the key deciding limitations. You can only create one text index on a collection (reference here), so you have no real choice. Additionally, MongoDB can only use one index at a time to satisfy a query (until index intersection is introduced in 2.6).
Hence, the only workable option is to create the compound index as you outlined, on both fields as a single index:
db.articles.ensureIndex(
{
title: "text",
abstract: "text",
},
{
weights: {
title: 1,
abstract:1,
},
name: "TextIndex"
}
)
The same remains true for 3 or 4 fields, you would first have to drop the existing index, then create the new index and include 3/4/other.
I want to do text search on these two keys.For example, the search text is "physics",and I want all the documents whose "title" or "abstract" contains keyword "physics" is returned.
To perform text search, MongoDB uses a text index and the $text operator.
MongoDB provides text indexes to support text search queries on string content. text indexes can include any field whose value is a string or an array of string elements.
To perform text search queries, you must have a text index on your collection. A collection can only have one text search index, but that index can cover multiple fields.
As per MongoDB BOL db.collection.ensureIndex() Deprecated since version 3.0.0:
db.collection.ensureIndex()
is now an alias for db.collection.createIndex()
.
The db.collection.ensureIndex()
Creates an index on the specified field if the index does not already exist.
Note: Use db.collection.createIndex() rather than db.collection.ensureIndex() to create new indexes.
Should I create two separate text indexes for both of them like this:
db.articles.ensureIndex({title:"text"})
db.articles.ensureIndex({abstract:"text"})
For example you can run the following in a mongo shell to allow text search over the name
and comments
fields:
> db.articles.createIndex( { title: "text", comments: "text" } )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
To make sure you have created the index on not through db.collection.getIndexes() Which returns an array that holds a list of documents that identify and describe the existing indexes on the collection. You must call db.collection.getIndexes() on a collection.
> db.articles.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.articles"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "title_text_comments_text",
"ns" : "test.articles",
"weights" : {
"comments" : 1,
"title" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]
>
Here the index name "title_text_comments_text" has created for both field.
So, No need to create again text index on specified both field.
should I create a index in a single command and give the equal weight:
db.articles.createIndex(
{
title: "text",
comments: "text"
}
)
My Answer is Yes .
Let's after creation of multiple fields for the text index ( like mention in your second scenario).
> db.articles.createIndex(
... {
... title: "text",
... comments: "text"
... }
... )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 2,
"note" : "all indexes already exist",
"ok" : 1
}
>
To verify from the db.collection.getIndexes()
method
> db.articles.getIndexes()
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "test.articles"
},
{
"v" : 2,
"key" : {
"_fts" : "text",
"_ftsx" : 1
},
"name" : "title_text_comments_text",
"ns" : "test.articles",
"weights" : {
"comments" : 1,
"title" : 1
},
"default_language" : "english",
"language_override" : "language",
"textIndexVersion" : 3
}
]
>
After execution of text index in mongo
shell, In the above statement we can see there come short note like "note" : "all indexes already exist"
.
So, we can say that both scenario
the creation of text index
is same.
Most Important Note : A collection can have at most
one
text index.
In the above example the database name is test
and collection name is articles
(Because as OP has used in their Code).