【问题标题】:Remove a ListField item by id using Mongoengine使用 Mongoengine 按 id 删除 ListField 项
【发布时间】:2014-07-10 17:17:24
【问题描述】:

我正在尝试通过使用 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"

【问题讨论】:

  • 尝试使用id_id = db.ObjectIdField(default=bson.ObjectId()) 将在模块加载时设置默认值——所以它们都将具有相同的ID!您需要使用可调用的 - 即错过()
  • @Ross 谢谢 - 你说得对,每次都会产生相同的 id - 在这种情况下,你如何建议为 EmbeddedDocument 生成唯一的 ObjectId(我想模仿 mongoengine 如何创建一个 id对于普通文件)
  • 你可以做兰巴:bson.ObjectId()

标签: python mongoengine flask-mongoengine


【解决方案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)

如果两个客户端同时尝试添加新帖子,上述解决方案可能会失败。他们可能有相同的_id。无法在 mongo 中的嵌入文档字段中强制执行唯一性。您只能使用客户端代码执行此操作。

解决方案 2:

制作一个单独的 cmets 集合。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-20
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    相关资源
    最近更新 更多