2016-08-06 67 views
0

ich eine Item-Klasse erstellt habe, und zwei Unterklassen element1 und Element2 wie untenFlask/Mongoengine: Fehler beim Versuch, mit statischer Methode Volltext-Suche auf Elternklasse auszuführen

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

Als nächstes erstellt i einige Elemente

Results in mongo shell of following commands db.item.find()/db.t1.find()/db.t2.find()

Alles ist in Ordnung, wenn ich die Methode Klasse testen bin

>>> 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") 
[] 
>>> 
Aber 10

, wenn ich die statische Methode verwendet werden soll (um sofort in allen Unterklassen suchen), habe ich diese Mongo Fehler:

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

Könnten Sie bitte helfen mit Ideen oder Tipps?

Antwort

1

Ich weiß, dies ist eine ziemlich alte Frage, aber ich fand es bei der Suche nach Lösungen für genau das gleiche Problem, und ich denke, ich würde meine Ergebnisse hier für die Nachwelt aufzeichnen.

Das Problem ist, dass Mongoengine automatisch _cls als Index für die Auflistung hinzufügt, wenn Sie eine Unterklasse mongoengine.Document ableiten. Wenn Sie anschließend versuchen, eine Volltextsuche für diese Sammlung mit der übergeordneten Klasse (der direkten Unterklasse des Dokuments) durchzuführen, enthält mongoengine ein $in Prädikat in der Abfrage für alle möglichen _cls Werte für dieses Dokument und alle Unterklassen. Leider ist dies nicht erlaubt, 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.

Beachten Sie, wenn Sie auf einem Ihrer Subklassen eine Textsuche zu tun, es funktioniert perfekt - das ist, weil mongoengine einen Gleichheitsvergleich in diesem Fall verwendet, die perfekt gültig ist.

Sie können dieses Problem beheben, indem Sie Ihre Indizes so anpassen, dass kein zusammengesetzter Textindex verwendet wird. Auf dem übergeordneten Dokument Unterklasse (Punkt in diesem Fall) passen Sie Ihre indexes Definition cls zu False einzustellen:

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

Diese im Mongoengine documentation dokumentiert. Ich hoffe das hilft wer auch immer diese Frage in der Zukunft kommt!