检查集合中是否存在某项的最佳方法?

时间:2019-07-03 15:33:14

标签: arrays mongodb performance optimization find

我对性能问题有些担心。我有一个cron,它每分钟运行一次,并更新一个集合。

每分钟从外部api获取10,000个新交易。其中一些交易记录已经在我的数据库中。

for (transaction in transactions) {
    if (Transaction.findOne(_id: transactionId, { _id: 1}))
        console.log("Already in db");
    else
        Transaction.insert(transaction)    

为加快速度,我将整个集合加载到内存中,并且仅在脚本末尾插入。

const toInsert = [];

const transactions = await Transaction.find().select(_id);
// I transform array of transactions to an object of transaction where key is _id, thus i can avoid using a find at every iteration
const transactionsObject = transactions.reduce((obj, transaction) => {
     obj[transaction.id] = true;
     return obj;
   }, {})

for (transaction in transactions) {
    if (transactionsObject[transactionId])
        console.log("Already in db");
    else {
        toInsert.push(transaction);
        transactionsObject[transaction._id] = true;
}

Transaction.insertMany(toInsert);

使用此脚本版本,该脚本非常快,但是我对可伸缩性有所担心,因为我将需要大量内存,并且如果需要对此进行线程化,则需要在线程之间共享所有内容。

您如何优化脚本?

1 个答案:

答案 0 :(得分:0)

让mongo计算丢失的文档可能很有意义。一种优化是仅找到您关心的交易的ID:

const transactionIds = await Transaction.find({_id: {$in: listOfIds}}).select(_id);

一种更快的替代方法是在id上创建唯一索引(默认的_id字段已经具有唯一索引),然后尝试使用{ordered: false}插入所有文档。某些插入操作将失败,但是让mongo进行计算会更快。

  

在将[set]设置为false的情况下,插入操作[将]对所有剩余文档继续进行。   https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/

> db.test.insertMany([{_id: 1}], { ordered: false })
{ "acknowledged" : true, "insertedIds" : [ 1 ] }
> db.test.insertMany([{_id: 1}, {_id: 2}], { ordered: false })
2019-07-03T16:25:54.402+0000 E QUERY    [js] BulkWriteError: write error at item 0 in bulk operation :
BulkWriteError({
    "writeErrors" : [
        {
            "index" : 0,
            "code" : 11000,
            "errmsg" : "E11000 duplicate key error collection: test.test index: _id_ dup key: { : 1.0 }",
            "op" : {
                "_id" : 1
            }
        }
    ],
    "writeConcernErrors" : [ ],
    "nInserted" : 1,
    "nUpserted" : 0,
    "nMatched" : 0,
    "nModified" : 0,
    "nRemoved" : 0,
    "upserted" : [ ]
})