我在mongo中拥有以下我的收藏结构。
class SkillCluster(DynamicDocument):
Name = StringField(required=True, unique=True)
SubClusters = ListField(StringField())
ModifiedDate = DateTimeField(default=datetime.utcnow)
meta = {
'indexes': ['ClusterName'],
'index_background': True,
'collection': 'SkillClusters',
'db_alias': db_alias_name
}
class Skill(DynamicDocument):
Name = StringField(required=True, unique=True)
Clusters = ListField(ReferenceField(SkillCluster))
ModifiedDate = DateTimeField(default=datetime.utcnow)
meta = {
'indexes': ['SkillName'],
'index_background': True,
'collection': 'Skill',
'db_alias': db_alias_name
}
SkillCluster集合的示例文档
{
"_id" : ObjectId("5ad089263b3f4f5d68d74d7f"),
"Name" : "Sciences",
"ModifiedDate" : ISODate("2018-04-13T10:40:38.152Z"),
"SubClusters" : [
"Biology",
"Biotech",
"Chemistry",
"General"
]
}
技能可能属于不同的集群,我在Clusters
集合中有一个Skill
列表字段。我已经提出了以下代码来添加技能
def add_skills(skill_name, cluster_string):
cluster_sub_clusters = cluster_string.split(':', 1)
cluster_name, sub_cluster_name = cluster_sub_clusters[0], cluster_sub_clusters[-1].strip()
# query to test if the "SkillCluster" collection has a document that has both the cluster_name in "Name" fields & sub_cluster_name in "SubClusters" array
result_set = SkillCluster.objects(Name=cluster_name, SubClusters__contains=sub_cluster_name)
if result_set:
data_dict = {
"ModifiedDate": datetime.utcnow(),
"Clusters": {
"$addToSet": result_set[0]
}
}
skill = Skill.objects(Name=skill_name).modify(upsert=True, new=True, **data_dict)
else:
# check if document exists with name = cluster_name, if so then add sub_cluster_name to the "SubClusters" array
result_set = SkillCluster.objects(Name=cluster_name)
if result_set:
result_set[0].update(add_to_set__SubClusters=sub_cluster_name)
# ........... rest of the logic
但是我收到了这个错误 -
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/queryset/transform.py", line 277, in update
value = field.prepare_query_value(op, value)
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/fields.py", line 708, in prepare_query_value
return [self.field.prepare_query_value(op, v) for v in value]
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/fields.py", line 708, in <listcomp>
return [self.field.prepare_query_value(op, v) for v in value]
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/fields.py", line 997, in prepare_query_value
super(ReferenceField, self).prepare_query_value(op, value)
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/base/fields.py", line 174, in prepare_query_value
self.validate(value)
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/fields.py", line 1003, in validate
self.error('A ReferenceField only accepts DBRef or documents')
File "/home/dimension/.virtualenvs/docparser/lib/python3.5/site-packages/mongoengine/base/fields.py", line 149, in error
raise ValidationError(message, errors=errors, field_name=field_name)
mongoengine.errors.ValidationError: A ReferenceField only accepts DBRef or documents
我应该如何向ListField添加引用对象。
谢谢。
修改函数的语法导致了问题。
MongoEngine为update()
和modify()
函数使用Django样式的更新关键字参数。所以也许你应该尝试这样的事情:
data_dict = {
#"ModifiedDate": datetime.utcnow(),
add_to_set__Clusters : result_set[0] # <= Django-style update/modify keyword arguments
}
skill = Skill.objects(Name=skill_name).modify(upsert=True, new=True, **data_dict)
以下是MongoEngine API参考的链接:http://docs.mongoengine.org/apireference.html搜索update()
和modify()
,还可以参考原子更新部分获取可能的更新关键字列表:http://docs.mongoengine.org/guide/querying.html#atomic-updates