MongoDB:$ addToSet / $ push文件只有在尚不存在时才会出现

时间:2010-12-05 01:12:26

标签: php mongodb

我有一个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值,两个示例都用新的替换整个嵌入文档。如果$push尚不存在,或者我需要在两个命令中执行此操作,是否只能members.email“成员”文档?

或者,将members放在他们自己的集合中,并使用类似parent_list的属性,是否可以更好地实现可伸缩性?

5 个答案:

答案 0 :(得分:5)

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

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

希望这有帮助。

答案 1 :(得分:1)

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

不会有嵌入式文件。您仍然可以使用list_id

中的find()

答案 2 :(得分:1)

在查询条件中使用$ne来过滤包含相同电子邮件成员的文档:

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

至于关于可伸缩性的第二个问题,它依赖于案例依赖...在父级中嵌入doc需要更难的更新和更大的数据获取,但减少了获取查询次数。