我刚遇到一个场景,我不知道如何用文档的现有结构来解决。如下所示,我显然可以通过一些重构来解决这个问题,但是我很好奇如何才能最有效地解决这一问题,并尊重相同的结构。在
请注意这个皇后区不同于How to Do An Atomic Update on an EmbeddedDocument in a ListField in MongoEngine?
假设以下模型:
class Scans(mongoengine.EmbeddedDocument):
peer = mongoengine.ReferenceField(Peers, required=True)
site = mongoengine.ReferenceField(Sites, required=True)
process_name = mongoengine.StringField(default=None)
documents = mongoengine.ListField(mongoengine.ReferenceField('Documents'))
is_complete = mongoengine.BooleanField(default=False)
to_start_at = mongoengine.DateTimeField()
started = mongoengine.DateTimeField()
finished = mongoengine.DateTimeField()
class ScanSettings(mongoengine.Document):
site = mongoengine.ReferenceField(Sites, required=True)
max_links = mongoengine.IntField(default=100)
max_size = mongoengine.IntField(default=1024)
mime_types = mongoengine.ListField(default=['text/html'])
is_active = mongoengine.BooleanField(default=True)
created = mongoengine.DateTimeField(default=datetime.datetime.now)
repeat = mongoengine.StringField(choices=REPEAT_PATTERN)
scans = mongoengine.EmbeddedDocumentListField(Scans)
我想做的是插入一个ScanSettings对象,当且仅当scans字段的所有元素-扫描列表嵌入的文档列表-依次具有唯一性时?我所说的unique是指数据库级别的列表中的所有元素,而不是整个列表—这很容易。在
在纯英语中,如果在插入ScanSetting时,scans列表的任何元素都有一个scans实例,其中的文档列表是重复的,那么这样的插入不应该发生。我的意思是数据库级别的唯一性,考虑到现有的记录(如果有的话)。在
鉴于Mongo不支持同一文档中列表的所有元素的唯一性,我找到了两个解决方案:
选项A
我重构了我的“模式”,并使Scans集合从Document继承而不是从Embedded Document继承,并将ScanSettings的Scans字段更改为ReferenceFields的ListField以扫描文档。然后很容易,因为我只需要先用“Updates”和操作符“add_to_set”和选项“upsert=True”保存扫描。一旦操作被批准,保存扫描设置。我需要扫描实例的数量来插入+1个查询。在
选项B 我保留了相同的“模式”,但不知何故为扫描嵌入的文档生成了唯一的id。然后,在插入带有非空scans字段的扫描设置之前,我将获取已经存在的记录,看看在刚刚检索到的记录和要插入的记录中是否存在重复的文档objectid。 换句话说,我会通过Python而不是使用MogoneEngine/Mongodb来检查唯一性。我需要2个扫描实例来插入(读取+用add_set_操作符更新)+1个扫描设置保存
选项C 忽略唯一性。考虑到我的模型将如何构建,我非常肯定不会有重复,或者如果有,它将是可以忽略不计的。然后在阅读时处理重复的内容。对于像我这样来自关系数据库的人来说,这个解决方案让人觉得很有吸引力。在
我是一个蒙哥新手,所以我很感谢你的评论。谢谢。在
PS:我正在使用最新的MongoEngine和免费的Mongodb。在
事先非常感谢。在
最后我选择了选项A,因此我将模型重构为:
a)创建一个继承自Document类的Mixin类,以添加两个方法:重写“save”,使其仅在唯一文档列表为空时允许保存;而“save”则允许在文档列表为空时保存和/或更新。这个想法是为了加强独特性。在
b)重构扫描和扫描设置,以便前者将“扫描”字段重新定义为扫描引用的列表字段,而后者将继承自文档而不是嵌入文档。在
c)实际情况是Scans和ScanSettings现在继承自Mixin类,因为这两个类需要分别保证其属性“documents”和“Scans”的唯一性。因此有了Mixin类。在
使用a)和b)我可以保证唯一性,并首先保存每个扫描实例,以便以后添加到中扫描设置.扫描以通常的方式。在
对我这样的新手来说有几点:
最后是密码。它还没有完全测试,但足以让我的主要想法正确。在
相关问题 更多 >
编程相关推荐