3

I'm trying to use the fulltext search. Setting the index in this way

myRootSchema.index({ "_type": 1, "$**": "text" }); 

where _type is a discriminatorKey and myRootSchema is the father schema of 4 inherited schemas.

I get this error

{
"name": "MongoError",
"message": "error processing query: ns=MYDB.caseNotesTree: TEXT : query=title, language=english, caseSensitive=0, diacriticSensitive=0, tag=NULL\nSort: {}\nProj: {}\n planner returned error: failed to use text index to satisfy $text query (if text index is compound, are equality predicates given for all prefix fields?)",
"waitedMS": 0,
"ok": 0,
"errmsg": "error processing query: ns=MYDB.caseNotesTree: TEXT : query=title, language=english, caseSensitive=0, diacriticSensitive=0, tag=NULL\nSort: {}\nProj: {}\n planner returned error: failed to use text index to satisfy $text query (if text index is compound, are equality predicates given for all prefix fields?)",
"code": 2
}

Trying this query

Model
    .find(
        { $text : { $search :req.query.q } }

    )
    .exec(function(err, data) {
        if(err)res.json(err)
        res.json(data)
    });

EDIT: as suggested, I should set the _type field in the query, but the _type is 'autofilled' since is a discriminator. A query with a single _type works, but I don't need that, I have to query 4 inherited models. I even tried an $or, doesn't work with the same error.

Model
    .find(
        {   $or: [ { _type: 'childA' },
            { _type: 'childB' },
            { _type: 'childC' },
            { _type: 'childD' }
        ], $text : { $search :req.query.q } }

    )
    .exec(function(err, data) {
        if(err)console.log(err)
        res.json(data)
    });
8
  • 1
    Possible duplicate of Combine full text with other index which actually answers the question rather than just quoting the documentation. Commented Mar 17, 2016 at 9:57
  • Is Model your root model or the model for one of your 4 inherited schemas? Commented Mar 17, 2016 at 12:55
  • Right, _type is only going to be added to your queries for the inherited models. Instead of that $or, have you tried adding _type: {$in: ['childA', 'childB', 'childC', 'childD']}? Commented Mar 17, 2016 at 14:30
  • nop, I've just tried, doesn't work. Commented Mar 17, 2016 at 14:37
  • Then I don't think you can query across multiple _type values while also using a $text query, which makes sense given how the compound index is constructed. You'll need to $text query each _type separately and then merge the results together; effectively creating your own $or query. Commented Mar 17, 2016 at 16:33

2 Answers 2

3

The error messages says "if text index is compound, are equality predicates given for all prefix fields?". That means, that in your query you are required to supply type as well. Your query does not do that, as it only uses the $text part, but not the type part of the index.

Sign up to request clarification or add additional context in comments.

2 Comments

Not necessarily true. The question mentions "discriminators" which is where the _type field is being filled from. Mongoose "automagically" ( love that term ) the exact value ( an equality prefix ) to all queries issued using the model assigned to the discriminator. So you don't need to include _type in the query explicitly when it is going to be filled in for you before it's sent to the server. Also already covered the issues with compound text indexes in another answer here.
I'm sorry I read the whole post but I don't get how fits my discriminator case. As you correctly noted the compound index in composed by the discriminator and the wildcard text. Please refer to my edit.
1

This is the limitation in MongoDB with "text" indexes. As per mongoDB documentation for a wildcard text index if there are any preceding keys then the query predicate must include equality matching condition on the preceding keys. Refer here for documentation.

The modified code bit $or: [ { _type: 'childA' },{ _type: 'childB' },{ _type: 'childC' },{ _type: 'childD' } can be seen as _type: {$in: ['childA', 'childB', 'childC', 'ChildD']} and it is not matching with the limitation specified i.e. there must be a equality condition.

To overcome this you can try creating the compound Index with the wild card text field first followed by other keys as given below.

myRootSchema.index({ "$**": "text" , "_type": 1}); 

This works fine. But it is not optimized.

If you are thinking of an optimized query then you must use the filters separately in two different queries until Mongo relax the limitations.

1 Comment

can you suggest how to explicitly filter by one field first and then do a text search in order to optimize for an $in condition like what you mentioned above? I am struggling with this atm

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.