MongoEngine - 从ListField中按ID提取引用
我想从一个 ListField(ReferenceField)
中删除一些引用,主要是根据它们的值来决定。
我在以下模型中存储关于图片的信息:
class ImageUrl(Document):
src = UrlField()
counter = IntField()
deleted = BooleanField()
我们在一个叫做 Webpage
的 EmbeddedDocument
中存储在页面上遇到的图片的 id
:
class Webpage(EmbeddedDocument):
image_list = ListField(ReferenceField(ImageUrl))
...
最后,Website
模型被嵌入到一个 RawData
模型中:
class RawData(Document):
...
webpage = EmbeddedDocumentField(Webpage)
我想根据一些属性(比如:计数器值超过1)从 RawData
记录中删除对 ImageUrl
记录的引用,然后将这些 ImageUrl
记录的 deleted
属性设置为 True
。
我正在做:
images = ImageUrl.objects((Q(deleted=False) & Q(counter__gt=1)).all()
for image in images:
# all RadData records containing the image in their image list
for rdata in RawData.objects(webpage__image_list__in=[image.id]:
# remove image from the image_list
RawData.objects(id=rdata.id).update_one(pull__webpage__image_list=image.id)
# set 'deleted=True' on the ImageUrl record
ImageUrl.objects(id=image.id).update_one(set__deleted=True)
但是,pull
操作出现了以下错误:
OperationError: Update failed [Cannot apply $pull/$pullAll modifier to non-array]
。
根据我从 http://docs.mongodb.org/manual/reference/operator/pull/#_S_pull 或 如何通过ID从MongoEngine的列表(ListField)中删除项目? 理解的,我需要指定要从中删除值的数组的键。然而,在我的情况下,我想从一个列表中删除一个值……我该怎么做呢?
非常感谢你的时间!
1 个回答
位置操作符的工作方式是,它允许你在一个列表中查找某个值,然后对这个值的第一个出现实例进行操作,通常是更新。$pull
会从列表中删除所有的实例,这正是你想要的效果。
在使用mongoengine时,如果有引用,你可以直接传入实例对象,比如:
for rdata in RawData.objects(webpage__image_list=image):
# remove image from the image_list
rdata.update_one(pull__webpage__image_list=image)
我整理了一下代码,去掉了重复的查询 - 因为你已经有了rdata
,所以不需要再去找那个文档了!
OperationError: Update failed [Cannot apply $pull/$pullAll modifier to non-array]
这意味着你正在尝试删除需要数组的数据,但有一个文档的image_list
实际上并不是一个数组。这可能是因为在磁盘上有一个文档的image_list
并不是一个列表。如果你加一个try except块,就可以查看那个失败的文档,看看是不是这种情况,如果是的话,就需要手动迁移一下。