8
votes

I am unable to retrieve documents when an array within an array of elements contains text that should match my search.

Here are two example documents:

{
    _id: ...,
    'foo': [
        {
            'name': 'Thing1',
            'data': {
                'text': ['X', 'X']
            }
        },{
            'name': 'Thing2',
            'data': {
                'text': ['X', 'Y']
            }
        }
    ]
}

{
    _id: ...,
    'foo': [
        {
            'name': 'Thing3',
            'data': {
                'text': ['X', 'X']
            }
        },{
            'name': 'Thing4',
            'data': {
                'text': ['X', 'Y']
            }
        }
    ]
}

By using the following query, I am able to return both documents: db.collection.find({'foo.data.text': {'$in': ['Y']}}

However, I am unable to return these results using the full text command/index: db.collection.runCommand("text", {search" "Y"})

I am certain that the full text search is working, as the same command issuing a search against "Thing1" will return the first document, and "Thing3" returns the second document.

I am certain that both foo.data.text and foo.name are both in the text index when using db.collection.getIndexes().

I created my index using: db.collection.ensureIndex({'foo.name': 'text', 'foo.data.text': 'text'}). Here are the indexes as shown by the above command:

    {
            "v" : 1,
            "key" : {
                    "_fts" : "text",
                    "_ftsx" : 1
            },
            "ns" : "testing.collection",
            "background" : true,
            "name" : "my_text_search",
            "weights" : {
                    "foo.data.text" : 1,
                    "foo.name" : 1,
            },
            "default_language" : "english",
            "language_override" : "language",
            "textIndexVersion" : 1
    }

Any suggestion on how to get this working with mongo's full text search?

1
Can you provide the full text index definition from db.collection.getIndexes()? Perhaps it does not include the foo.data.text field? I would note that both of your examples in the question description currently have syntax errors. The find() uses the incorrect field name (txt instead of text) and should be: db.collection.find({'foo.data.text': {'$in': ['Y']}}). The fulltext search should be db.fulltext.runCommand("text", {search:"Y"}). I tried both with MongoDB 2.4.6 using your example documents and got results as expected. - Stennie
Thanks for your comment. This is strictly an example. I've updated to fix syntax. Like I stated, db.collection.getIndex() shows that the index exists. - earthmeLon
I've added the .getIndex() output. - earthmeLon

1 Answers

11
votes

Text search does not currently support indexed fields of nested arrays (at least not explicitly specified ones). An index on "foo.name" works fine as it is only one array deep, but the text search will not recurse through the subarray at "foo.data.text". Note that this behavior may change in the 2.6 release.

But fear not, in the meantime nested arrays can be text-indexed, just not with individually specified fields. You may use the wildcard specifier $** to recursively index ALL string fields in your collection, i.e.

db.collection.ensureIndex({"$**": "text" }

as documented at http://docs.mongodb.org/manual/tutorial/create-text-index-on-multiple-fields/ . Be careful though as this will index EVERY string field and could have negative storage and performance consequences. The simple document structure you describe though should work fine. Hope that helps.