Самый лучший способ проверить, существует ли предмет в коллекции? - PullRequest
0 голосов
/ 03 июля 2019

У меня есть некоторые опасения по поводу проблемы с производительностью. У меня есть cron, который запускается каждую минуту и ​​обновляет коллекцию.

Каждую минуту 10 000 новых транзакций извлекаются из внешнего API. Некоторые из этих записей транзакций уже есть в моей базе данных.

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 голосов
/ 03 июля 2019

Возможно, имеет смысл позволить Монго вычислить, какие документы отсутствуют. Одной из оптимизаций будет поиск только идентификаторов транзакций, которые вас интересуют:

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

Еще более быстрой альтернативой было бы создание уникального индекса для вашего идентификатора (поле _id по умолчанию уже имеет уникальный индекс), а затем попытка вставить все документы с помощью {ordered: false}. Некоторые вставки завершатся неудачно, но если Монго выполнит этот расчет, будет быстрее.

Если для параметра [установлено] установлено значение 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" : [ ]
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...