我正在尝试使用mongoengine通过定位列表项的_id来从ListField中删除项目 - 我在这里引用了有关原子更新的mongoengine文档:http://docs.mongoengine.org/guide/querying.html#atomic-updates
模型
class Prospect(db.Document):
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
class Comment(db.EmbeddedDocument):
_id = db.ObjectIdField(default=bson.ObjectId())
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
body = db.StringField(verbose_name="Note", required=True)
author = db.StringField(verbose_name="Name", max_length=255, required=True)
Mongo文档如下所示:
...
"comments": [
{
"_id": {
"$oid": "53bebb55c3b5a0db7829c15f"
},
"created_at": {
"$date": "2014-07-09T18:26:58.444Z"
},
"body": "Did something\n",
"author": "Dave Roma"
},
我试图删除这样的评论:
prospect = Prospect.objects(id=request.form['prospect_id']).update_one(pull___id=request.form['comment_id'])
我收到的是mongoengine invalidQueryError:
InvalidQueryError: Cannot resolve field "_id"
答案 0 :(得分:1)
您的问题的答案将是:
prospect = Prospect.objects(id=request.form['prospect_id']).update_one(pull__comments__id=request.form['comment_id'])
您的原始查询试图在mongoengine中找到明显不存在的_id
字段。
现在解决你在评论中谈到的问题。
解决方案1:
class Prospect(db.Document):
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
def get_next_comment_id(self):
return len(self.comments)+1
def add_new_comment(self, author, body):
self.update(add_to_set__comments=Comment(_id=self.get_next_comment_id(), author=author, body=body)
class Comment(db.EmbeddedDocument):
_id = db.IntField(required=True)
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
body = db.StringField(verbose_name="Note", required=True)
author = db.StringField(verbose_name="Name", max_length=255, required=True)
如果两个客户端尝试同时添加新帖子,则上述解决方案可能会失败。他们可能有sam e _id。无法在mongo中的嵌入式文档字段中强制实现唯一性。您只能使用客户端代码执行此操作。
解决方案2:
制作单独的评论集。
class Prospect(db.Document):
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
class Comment(db.Document):
on_prospect = db.ReferenceField(Prospect)
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
body = db.StringField(verbose_name="Note", required=True)
author = db.StringField(verbose_name="Name", max_length=255, required=True)
def add_new_comment(prospect, author, body):
comment = Comment(on_prospect = prospect, author=author, body=body).save()
return comment.id
def get_all_posts_on_prospect(prospect):
return Comment.objects(on_prospect = prospect).order_by('-id')
每个评论都会给出唯一的ID。
解决方案3:
这只是一个想法,我不确定利弊。
class Prospect(db.Document):
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
def get_id_for_comment(self, comment):
return self.comments.index(comment)
class Comment(db.EmbeddedDocument):
_id = db.IntField()
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
body = db.StringField(verbose_name="Note", required=True)
author = db.StringField(verbose_name="Name", max_length=255, required=True)
def add_new_comment(prospect, author, body)
comment = Comment(_id=self.get_next_comment_id(), author=author, body=body)
prospect.update(add_to_set__comments = comment)
cid = prospect.get_id_for_comment(comment)
prospect.update(set__comments__cid__id = cid)
return cid