5

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?

1
  • Not a direct answer to your question, because I would basically have to test, but a recommendation: if possible you should use the 2.6 (RC1 as of time of writing this) to do any testing. Full text search goes from a beta feature to a production feature with the release of 2.6 and it is fully integrated into the query operators and the aggregation framework.
    – Adam C
    Commented Mar 11, 2014 at 15:21

2 Answers 2

1

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.

1

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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.