在 MongoDB 和 MongoEngine 中,使用 EmbeddedDocument 时可能会遇到需要通过 EmbeddedDocument 对象来获取其对应的 Document 对象的情况。例如,在以下代码中,我们定义了一个 EmbeddedDocument 类 ToySale,它具有 end_time 和 percentage 字段,并定义了一个属性 super_price,该属性可以根据 ToySale 中的字段值计算出 Toy 的价格。
from mongoengine import EmbeddedDocument, Document, FloatField, IntField
class ToySale(EmbeddedDocument):
end_time = FloatField()
percentage = IntField()
@property
def super_price(self):
return self.toy.price - (self.percentage * self.toy.price / 100)
class Toy(Document)
sale = EmbeddedDocumentField(ToySale)
price = IntField()
在上述代码中,我们希望在 ToySale 的 super_price 属性中访问 Toy 的 price 字段。但是,在 MongoEngine 中,EmbeddedDocument 类没有类似 Django ORM 中的 ‘related_name’ 机制,因此我们无法直接通过 ToySale 对象来访问 Toy 的字段。
2、解决方案
解决方案一:通过 EmbeddedDocument 字段查询
我们可以通过 EmbeddedDocument 的字段来查询对应的 Document 对象。例如,如果我们知道 ToySale 的 end_time 字段的值,我们可以使用以下代码来查询 Toy 对象:
Toy.objects(sale__end_time=3.14)
如果我们知道 ToySale 的 percentage 字段的值,我们可以使用以下代码来查询 Toy 对象:
Toy.objects(sale__percentage=3)
如果我们知道 ToySale 的 end_time 和 percentage 字段的值,我们可以使用以下代码来查询 Toy 对象:
Toy.objects(sale__end_time=3.14, sale__percentage=3)
解决方案二:通过 EmbeddedDocument 对象查询
如果我们已经有一个 ToySale 对象,我们可以使用以下代码来查询对应的 Toy 对象:
Toy.objects(**{'sale__' + key: value
for key, value in toy_sale.to_mongo().items()
if not key.startswith('_')})
或者,我们可以使用以下更简单的代码:
Toy.objects(sale=toy_sale)
代码示例:
from mongoengine import connect
import datetime
connect('mongodb://localhost:27017', db='test_database')
class ToySale(EmbeddedDocument):
end_time = FloatField()
percentage = IntField()
@property
def super_price(self):
return self.toy.price - (self.percentage * self.toy.price / 100)
class Toy(Document)
sale = EmbeddedDocumentField(ToySale)
price = IntField()
toy1 = Toy(price=100)
toy1.sale = ToySale(end_time=datetime.datetime.now(), percentage=20)
toy1.save()
toy2 = Toy(price=200)
toy2.sale = ToySale(end_time=datetime.datetime.now(), percentage=10)
toy2.save()
# 查询 Toy 对象,其 sale.end_time 字段值为 datetime.datetime.now()
toys1 = Toy.objects(sale__end_time=datetime.datetime.now())
print(toys1)
# 查询 Toy 对象,其 sale.percentage 字段值为 10
toys2 = Toy.objects(sale__percentage=10)
print(toys2)
# 查询 Toy 对象,其 sale.end_time 字段值为 datetime.datetime.now() 且 sale.percentage 字段值为 10
toys3 = Toy.objects(sale__end_time=datetime.datetime.now(), sale__percentage=10)
print(toys3)
# 获取第一个 Toy 对象的 ToySale 对象
toy_sale = toy1.sale
# 通过 ToySale 对象查询 Toy 对象
toy = Toy.objects(sale=toy_sale)
print(toy)