Python 在EmbeddedDocumentList中匹配EmbeddedDocument
所以我有这个测试数据,比如mongo,Cart模型:Python 在EmbeddedDocumentList中匹配EmbeddedDocument,python,django,mongodb,mongoengine,Python,Django,Mongodb,Mongoengine,所以我有这个测试数据,比如mongo,Cart模型: { "_id" : ObjectId("55eb513c516ddc8fa6e68886"), "user" : ObjectId("55e3f236516ddc78296968be"), "items" : [ { "item" : ObjectId("55eb10b8516ddc7508dba7c2"), "quantity" : 1,
{
"_id" : ObjectId("55eb513c516ddc8fa6e68886"),
"user" : ObjectId("55e3f236516ddc78296968be"),
"items" : [
{
"item" : ObjectId("55eb10b8516ddc7508dba7c2"),
"quantity" : 1,
"added_date" : ISODate("2015-09-05T20:32:16.527Z"),
"coupons" : ObjectId("55eb10cd516ddc751d3d5e25"),
"order_type" : [
"in_store",
"curbside"
]
},
{
"item" : ObjectId("55eb10b8516ddc7508dba7cc"),
"quantity" : 1,
"added_date" : ISODate("2015-09-05T20:32:16.527Z"),
"coupons" : ObjectId("55eb10cd516ddc751d3d5e25")
},
{
"item" : ObjectId("55eb10b8516ddc7508dba7c8"),
"quantity" : 1,
"added_date" : ISODate("2015-09-05T20:32:16.527Z"),
"coupons" : ObjectId("55eb10cd516ddc751d3d5e25")
}
]
}
以下是我的模型:
class CartItem(mongoengine.EmbeddedDocument):
item = mongoengine.ReferenceField('Item')
quantity = mongoengine.IntField()
added_date = mongoengine.DateTimeField( default=timezone.now() )
coupons = mongoengine.ReferenceField('Coupon')
order_type = mongoengine.ListField(mongoengine.StringField(choices=ORDER_TYPE_CHOICES))
class Cart(mongoengine.Document):
user = mongoengine.ReferenceField('User')
items = mongoengine.EmbeddedDocumentListField(CartItem)
savings = mongoengine.DecimalField(precision=2, default=0)
现在,我希望能够获得CartItems,例如,这些CartItems只有的订单类型“in\u store”。所以我是这样说的:
cart = Cart.objects.filter(id="id")
items = cart.items
curbside_items = items.filter(order_type="curbside")
这不会返回任何内容。所以我试着这样做:
curbside_items = items.filter(order_type__math="curbside")
但这并没有给我任何回报。所以我的问题是如何在mongoengine中做到这一点。谢谢 MongoEngine使用for属性转换为MongoDB查询的形式。因此,您要查找的属性的“父级”是“项”,这意味着您引用了完整的路径,如下所示:
Cart.objects.filter(items__order_type="in_store")
其中文档在项
数组中包含作为订单类型
条目的“in_store”。请注意,这将返回“整个文档”,而不仅仅是匹配的条目。在response中还有其他处理方法
一种方法是使用底层pymongo驱动程序获得“原始”结果:
Cart._get_collection().find(
{ "items.order_type": "in_store" },
{ "items.$": 1 }
)
它利用运算符仅返回匹配的数组元素
或者对于“多重”匹配,则需要.aggregate()
:
或者通过$filter
在未来的版本中更具意义:
Cart._get_collection().aggregate([
{ "$match": {
"items.order_type": "in_store"
}},
{ "$project": {
"items": {
"$filter": {
"input": "$items",
"as": "el",
"cond": { "$eq": [ "$$el.order_type", "in_store" ] }
}
}
}}
])
“djangoesque”行中的标准mongoengine查询不支持此类操作,只返回未修改的整个文档。对于
$slice
来说是一个例外,这里有一个选项,可以执行与本机MongoDB对应的操作。这让我得到了cart,但我想得到CartItem。我更新了帖子来表达我的意思。谢谢@布伦登:你没有真正理解我说的话,是吗?Mongoengine不支持mongodb查询通常提供的那种“投影”。如果您只想获取“匹配项”,那么您需要在代码中完成,因为mongoengine不会仅从数组“only”中检索匹配项。它需要文档中存在的整个数组。或者您可以改为使用“原始”查询,直接从底层pymongo驱动程序检索基本python对象。@Brenden1995阅读上面的内容怎么样。有足够多的证据来澄清每一个案例。
Cart._get_collection().aggregate([
{ "$match": {
"items.order_type": "in_store"
}},
{ "$project": {
"items": {
"$filter": {
"input": "$items",
"as": "el",
"cond": { "$eq": [ "$$el.order_type", "in_store" ] }
}
}
}}
])