Q:

Flask/Mongoengine : Error while trying to perform full-text-search on parent class with static method

I've created an Item class, and two subclasses Item1 and Item2 as below
class Item(db.Document):
    name            =   db.StringField()
    slug            =   db.StringField()
    description     =   db.StringField()
    content         =   db.StringField()
    start_time      =   db.DateTimeField()
    end_time        =   db.DateTimeField()

    @staticmethod
    def search_static(keywords):
        return Item.objects.search_text(keywords).order_by('$text_score')

    @classmethod
    def search_class(cls,keywords):
        return cls.objects.search_text(keywords).order_by('$text_score')

    meta = {
        'allow_inheritance' : True,
        'indexes'           : [
            {
                'fields': ['$name','$slug','$description','$content'],
                'default_language':'french',
                'weights': {'name': 10, 'slug': 10 , 'description': 5, 'content': 5}
            }
        ]
    }

class Item1(Item):
    item_type       =   db.ReferenceField('T1')

class Item2(Item):
    item_type       =   db.ReferenceField('T2')

class T1(db.Document):
    name            =   db.StringField()

class T2(db.Document):
    name            =   db.StringField()

Next, i created some items
Results in mongo shell of following commands db.item.find() / db.t1.find() / db.t2.find()
Everything is fine when i'm testing the class method 
>>> Item1.search_class("dog")
[<Item1: Item1 object>, <Item1: Item1 object>]
>>> Item1.search_class("viper")
[<Item1: Item1 object>]
>>> Item2.search_class("viper")
[<Item2: Item2 object>]
>>> Item2.search_class("tiger")
[]
>>> 

But when I want to use the static method (in order to search in all the subclasses at once), I have this mongo error:
>>> Item.search_static("tiger")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/venv/lib/python2.7/site-packages/mongoengine/queryset/queryset.py", line 58, in __repr__
    self._populate_cache()
  File "/venv/lib/python2.7/site-packages/mongoengine/queryset/queryset.py", line 92, in _populate_cache
    self._result_cache.append(self.next())
  File "/venv/lib/python2.7/site-packages/mongoengine/queryset/base.py", line 1407, in next
    raw_doc = self._cursor.next()
  File "/venv/lib/python2.7/site-packages/pymongo/cursor.py", line 1090, in next
    if len(self.__data) or self._refresh():
  File "/venv/lib/python2.7/site-packages/pymongo/cursor.py", line 1012, in _refresh
    self.__read_concern))
  File "/venv/lib/python2.7/site-packages/pymongo/cursor.py", line 905, in __send_message
    helpers._check_command_response(doc['data'][0])
  File "/venv/lib/python2.7/site-packages/pymongo/helpers.py", line 196, in _check_command_response
    raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: error processing query: ns=archives_flask.itemTree: $and
    _cls $in [ "Item" "Item.Item1" "Item.Item2" ]
    TEXT : query=tiger, language=french, caseSensitive=0, diacriticSensitive=0, tag=NULL
Sort: { _text_score: { $meta: "textScore" } }
Proj: { _text_score: { $meta: "textScore" } }
 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?)
>>> 

Could you please assist with any ideas or tips ?

A:

I realize this is a pretty old question, but I found it while searching for solutions to exactly the same problem and I figure I would record my findings here for posterity.
The issue is that when you subclass a mongoengine.Document subclass, mongoengine automatically adds _cls as an index on the collection. When you subsequently try to do a full text search on that collection using the parent class (the direct subclass of Document), mongoengine will include a $in predicate in the query for all of the possible _cls values for this Document and all of it's subclasses. Unfortunately this is not allowed, as documented in the MongoDB docs:

If the compound text index includes keys preceding the text index key, to perform a $text search, the query predicate must include equality match conditions on the preceding keys.

Note that if you do a text search on one of your subclasses, it works perfectly - this is because mongoengine uses an equality predicate in that case, which is perfectly valid.
You can resolve this issue by adjusting your indexes to not use a compound text index. On your parent Document subclass (Item in this case) adjust your indexes definition to set cls to False:
meta = {
    'allow_inheritance' : True,
    'indexes'           : [
        {
            'fields': ['$name','$slug','$description','$content'],
            'default_language':'french',
            'weights': {'name': 10, 'slug': 10 , 'description': 5, 'content': 5},
            'cls': False
        }
    ]
}

This is documented in the Mongoengine documentation.
I hope this helps whoever comes across this question in the future!

