将项添加到mongoengine中的ReferenceField列表中

问题描述 投票:0回答:1

我在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添加引用对象。

谢谢。

python pymongo mongoengine
1个回答
0
投票

修改函数的语法导致了问题。

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

© www.soinside.com 2019 - 2024. All rights reserved.