mongodb:如果不存在则插入

新手上路,请多包涵

每天,我都会收到一批文件(更新)。我想要做的是插入每个尚不存在的项目。

  • 我还想记录我第一次插入它们的时间,以及我最后一次在更新中看到它们的时间。
  • 我不想有重复的文件。
  • 我不想删除以前保存但不在我的更新中的文档。
  • 95%(估计)的记录每天都没有被修改。

我正在使用 Python 驱动程序 (pymongo)。

我目前做的是(伪代码):

 for each document in update:
      existing_document = collection.find_one(document)
      if not existing_document:
           document['insertion_date'] = now
      else:
           document = existing_document
      document['last_update_date'] = now
      my_collection.save(document)

我的问题是它非常慢(少于 100 000 条记录需要 40 分钟,而我在更新中有数百万条记录)。我很确定有一些内置的东西可以做到这一点,但是 update() 的文档是嗯……有点简洁……( http://www.mongodb.org/display/DOCS/Updating

有人可以建议如何更快地做到这一点吗?

原文由 LeMiz 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 484
2 个回答

听起来你想做一个 upsert 。 MongoDB 内置了对此的支持。将一个额外参数传递给您的 update() 调用: {upsert:true} 。例如:

 key = {'key':'value'}
data = {'key2':'value2', 'key3':'value3'};
coll.update(key, data, upsert=True); #In python upsert must be passed as a keyword argument

这完全取代了您的 if-find-else-update 块。如果密钥不存在,它将插入,如果存在,它将更新。

前:

 {"key":"value", "key2":"Ohai."}

后:

 {"key":"value", "key2":"value2", "key3":"value3"}

您还可以指定要写入的数据:

 data = {"$set":{"key2":"value2"}}

现在,您选择的文档将仅更新 key2 的值,而其他所有内容保持不变。

原文由 Van Nguyen 发布,翻译遵循 CC BY-SA 4.0 许可协议

从 MongoDB 2.4 开始,您可以使用 $setOnInsert ( http://docs.mongodb.org/manual/reference/operator/setOnInsert/ )

Set insertion_date using $setOnInsert and last_update_date using $set in your upsert command.

将您的伪代码变成一个工作示例:

 now = datetime.utcnow()
for document in update:
    collection.update_one(
        filter={
            '_id': document['_id'],
        },
        update={
            '$setOnInsert': {
                'insertion_date': now,
            },
            '$set': {
                'last_update_date': now,
            },
        },
        upsert=True,
    )

原文由 andy 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题