【问题标题】:Checking if record exists in MongoDB检查MongoDB中是否存在记录
【发布时间】:2013-05-29 04:28:24
【问题描述】:

我正在构建一个 MongoDB 数据库,问题是我想避免重复条目。目前我正在这样做(仅在检查条目是否不存在后插入文档):

from pymongo import Connection 
import pandas as pd
from time import strftime
from collections import OrderedDict

connection = Connection()
db = connection.mydb 
collection = db.mycollection

data = pd.read_csv("data/myfile.csv", parse_dates=[2,5])

for i in range(len(data)):
    if(collection.find({ "id":     data.ix[0],                         \
                         "date1":  data.ix[i, 2].strftime("%Y-%m-%d"), \
                         "date2":  data.ix[i, 5].strftime("%Y-%m-%d"), \
                         "number": int(data.ix[i, 6]),                 \
                         "type":   data.ix[i, 7]}).count() == 0):
        collection.insert(here goes what I'd like to insert)

这确实可以正常工作,但这已经存在严重的性能问题(只有大约 100Mb 的数据),因为每次执行 find() 似乎都会显着减慢速度。

有没有办法加快速度?也许我从根本上做错了? 我只需要避免在某些字段上重复,而不是所有字段(即,还有“number2”,它可以不同,但​​如果所有其他字段都匹配,我仍然希望它重复)。

【问题讨论】:

    标签: python performance mongodb pymongo


    【解决方案1】:

    您可以在要搜索的字段上构建unique index(mongo shell 语法):

    db.mycollection.ensureIndex({_id:1, date1:1, date2:1, number:1, type:1}, {unique: true});
    

    并在插入重复项时捕获约束违规异常(如果合适,则忽略它)。

    通常这应该会提高性能,因为重复检查是通过索引查找完成的。

    【讨论】:

      【解决方案2】:

      插入前检查不是防止它的好方法。为防止键重复,请使用主键。见how to set a primary key in mongodb

      另外如果对你不好,至少加mongo index

      解决这个问题的最好方法(我认为)是从所有相关字段中生成密钥,然后执行 2 个中的 1 个:

      1. 检查那个键,如果它是索引 - 会更快
      2. 将此键设为主键,插入将失败

      【讨论】:

      • 您不必将某个东西作为主键来拥有唯一索引!
      【解决方案3】:

      您可以使用 Upsert 标志执行 update() 操作,请参阅 Update Operations with the Upsert Flag。

      另外,MongoDB 中已经有一个名为“_id”的内置 id,因此您可以根据需要使用它。 下面是它的样子:

      collection.update(
          { "_id": ObjectID(data.ix[0]),
            "date1": data.ix[i, 2].strftime("%Y-%m-%d")
          }, 
          { "_id": ObjectID(data.ix[0]),
            "date1": data.ix[i, 2].strftime("%Y-%m-%d")
          },
          True
          )
      

      【讨论】:

      • 是的,我想我错过了这个问题(这正在加快速度)。也许这可以作为一个附加信息,即有一个可以替换 find() + insert() 的 upsert 操作。如果你们认为这只会混淆事物,我可以删除这个答案:)
      • 我确实认为 upsert 是相关的 - 它是“查找文档,如果你更新它,如果你不插入它”的答案,但我认为这与最初的问题不同(如果存在,他什么都不想做)...
      猜你喜欢
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 2015-01-21
      • 2012-08-13
      • 2015-01-02
      相关资源
      最近更新 更多