【问题标题】:MongoDB: $addToSet/$push document only if it doesn't already existMongoDB:$addToSet/$push 仅当文档不存在时
【发布时间】:2014-06-26 16:25:39
【问题描述】:

我有一个lists 集合,其中每个文档都有一个members 数组。 members 数组的每个元素都是一个具有email 属性、创建date 属性和一些其他元的文档。我在members.email 上有一个唯一索引,以防止同一电子邮件被两次输入到同一个列表中,但我想保留原来的date 值。不幸的是,$addToSet$push 似乎都没有这样做。

使用 $push 的示例:

$lists->update(array('_id' => $list['_id'], 'members.email' => array('$ne' => $email)), array('$push' => array('members' => array(
    'email' => $email,
    'date' => new MongoDate(),
    // etc.
))));

还有 $addToSet:

$lists->update(array('_id' => $list['_id']), array('$addToSet' => array('members' => array(
    'email' => $email,
    'date' => new MongoDate(),
    // etc.
))));

由于(我假设)唯一的 date 值,这两个示例都将整个嵌入文档替换为新文档。如果members.email 尚不存在,是否可以仅$push“成员”文档,或者我需要在两个命令中执行此操作?

或者,将members 放入具有parent_list-like 属性的集合中会更好吗?

【问题讨论】:

    标签: php mongodb


    【解决方案1】:

    根据我的经验,您不能“$push”或“$addToSet”的原因是因为您的目标“成员”可能是一个嵌入式对象(或在创建后转换为一个对象)。您只能在嵌入式数组上使用 $push、$pushAll、$addToSet...

    不幸的是,对于我们 php 开发人员来说,游标查询总是以数组形式返回数据,检查“members”之类的东西是数组还是对象的最佳方法是在 mongo shell 中运行 find() 并查看结果中的大括号/方括号(“{}”或“[]”)。

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      为什么没有一个集合来存储 list_id、email、added_date 然后,您将在 2 个键 list_id 和 email 上创建一个唯一索引。这将阻止插入 具有相同 list_id 和电子邮件的记录

      不会有嵌入文档。您仍然可以通过 list_id 使用 find()

      【讨论】:

        【解决方案3】:

        在查询条件中使用$ne 过滤具有同一电子邮件成员的文档:

        $lists->update(array('_id' => $list['_id'],
                             'members.email' => array('$ne' => $email)), 
                       array('$addToSet' => array('members' => array(
                             'email' => $email,
                             'date' => new MongoDate(),
                              // etc.
        ))));
        

        【讨论】:

          【解决方案4】:

          是的,这是可能的。查看 mongoDB advanced queries 部分中的 $exists 运算符。将 $exists 条件编码到 where 语句中,以便仅在成员电子邮件不存在时更新。

          【讨论】:

          • 我几乎肯定 $exists 不是我正在寻找的解决方案。
          【解决方案5】:

          IIUC,尝试使用Upsert 更新嵌入式文档(如果有)或插入它(如果没有)。也见this

          关于可伸缩性的第二个问题,它确实取决于具体情况...将文档嵌入父级需要更难的更新和更大的数据提取,但会减少提取查询数。

          【讨论】:

            猜你喜欢
            • 2015-04-29
            • 1970-01-01
            • 2017-06-30
            • 1970-01-01
            • 1970-01-01
            • 2020-07-03
            • 1970-01-01
            • 1970-01-01
            • 2014-09-09
            相关资源
            最近更新 更多