2016-05-09 3 views
1

Ich benutze Mongoengine mit Django.Mongoengine Filterabfrage in der Liste eingebettetes Feld basierend auf dem letzten Index

Ich habe ein eingebettetes Feld in meinem Modell. Das ist ein Listenfeld von eingebetteten Dokumenten.

import mongoengine 

class OrderStatusLog(mongoengine.EmbeddedDocument): 
    status_code = mongoengine.StringField() 

class Order(mongoengine.DynamicDocument): 
    incr_id = mongoengine.SequenceField() 
    status = mongoengine.ListField(mongoengine.EmbeddedDocumentField(OrderStatusLog)) 

Jetzt möchte ich das Ergebnis auf Order Sammlung filtern, basierend auf dem letzten Wert in status Feld.

z.B. Order.objects.filter(status__last__status_code="scode")

Ich denke, es gibt keine solche Sache __last. Ich habe versucht, den Ansatz in der Doku http://docs.mongoengine.org/guide/querying.html#querying-lists erwähnt, hat aber nicht funktioniert.

Ich kann dies lösen, indem ich alle Dokumente in der Sammlung überschlinge, aber das ist nicht effizient, wie können wir diese Abfrage effizient schreiben.

+0

Ich denke, Sie sollten Ihre Frage Python zu markieren, so dass 1/es als Python Frage 2 aufgeführt ist/es bekommt automatische Syntax-Highlighting. (Alternativ können Sie '' vor dem Codeblock angeben: http://stackoverflow.com/editing-help#syntax-highlighting) –

Antwort

1

Ich bin nicht sicher, dass MongoEngine das (noch) tun kann. AFAIK, müssten Sie die Aggregationspipeline verwenden.

In der Shell Mongo, die '$slice' und die $arrayElemAt Operatoren:

db.order.aggregate([{ $project: {last_status: { $arrayElemAt: [{ $slice: [ "$status", -1 ] }, 0 ]} }}, {$match: {'last_status.status_code':"scode"}} ]) 

Und in Python:

pipeline = [ 
    {'$project': {'last_status': { '$arrayElemAt': [{ '$slice': [ "$status", -1 ] }, 0 ]} }}, 
    {'$match': {'last_status.status_code':'scode'}} 
] 

agg_cursor = Order.objects.aggregate(*pipeline) 

result = [ Order.objects.get(id=order['_id']) for order in agg_cursor ] 

Der hier Trick ist, dass objects.aggregate einen Cursor PyMongo liefert, kein MongoEngine Cursor Wenn Sie also MongoEngine Objekte benötigen, können Sie in zwei Schritten vorgehen: Filtern Sie zuerst mithilfe des Aggregationsframeworks, um die IDs der übereinstimmenden Elemente zu erhalten, und holen Sie sie dann Gh A MongoEngine Abfrage.

Das ist was ich tue. Von meinen Tests hat es sich als viel effizienter erwiesen, als alles zu holen und den Python-Code zu filtern.

Wenn es einen einfacheren Weg gibt, bin ich daran interessiert, darüber zu hören. Andernfalls könnte dies eine Feature-Anforderung für MongoEngine sein. Möglicherweise möchten Sie ein Problem there öffnen.

+0

Danke Jerome. Ich versuchte es mit dem zweiten und es funktioniert. Vielen Dank. –

Verwandte Themen