приращение mongodb, если существует, вставьте - PullRequest
0 голосов
/ 02 мая 2018

В приведенном ниже коде я хочу вставить значение, если itemId и отметка времени не существует, в противном случае, если оно уже существует, я хочу увеличить его

Collection.update({
                itemId: itemId,
                timestamp: moment.unix(timestamp).set('seconds', 0).toDate(),
            },
            {
                '$inc': {
                    'data.ph1': data.ph1,
                    'data.ph2': data.ph2,
                    'data.ph3': data.ph3,
                    'data.total': data.total
                },
            },
            { upsert: true },
            (err,resp) => {
                if(err) {
                    reject(err);
                } else {  
                    resolve('minute value incremented' + gatewayId );
                }
            });

В итоге создается несколько документов. Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

У вас по-прежнему есть часть в миллисекундах (или, по крайней мере, так будет выглядеть), поэтому будет вставлен новый документ, если эта часть уникальна в течение текущей минуты.

Вот ваш код, который неправильно оставляет миллисекунды на месте:

var timestamp = ( Date.now() / 1000 );

console.log(new Date());
console.log(timestamp);
console.log(moment.unix(timestamp).set("seconds",0).toDate());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>

И когда вы удаляете и миллисекунды, это правильно:

var timestamp = ( Date.now() / 1000 );

console.log(new Date());
console.log(timestamp);
console.log(moment.unix(timestamp).set("seconds",0).set("milliseconds",0).toDate());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>

Или просто округлите значение timestamp, прежде чем передать его:

var timestamp = ( Date.now() / 1000 )
console.log(new Date());
timestamp = timestamp - ( timestamp % 60 );
console.log(timestamp);
console.log(moment.unix(timestamp).toDate());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.min.js"></script>

Так что, когда дата фактически округляется до «минуты», как вы ожидали, тогда все в порядке.

Суть в том, что «upsert» происходит только тогда, когда предоставленные условия (по сути, «ключ» документа) фактически не соответствуют ни одному существующему документу, поэтому что-то явно отличается в каждом запросе и наиболее вероятно кандидат - это значение timestamp в вашем коде и его последующее преобразование.

Тем не менее, если вы на самом деле не читаете timestamp из внешнего или уже определенного источника, тогда лучший способ получить "текущее время" - просто использовать ванильные Date методы:

var timestamp = Date.now();
timestamp = timestamp - ( timestamp % ( 1000 * 60 ) );
console.log(new Date(timestamp));

Это должно сделать эту работу без необходимости возиться с дополнительными импортированными библиотеками.

Таким образом, вам действительно нужно посмотреть, почему у вас есть текущий код, и если вы читаете уже определенное значение, то фактически «гарантируете», что миллисекунды и секунды удаляются при округлении, как обычно лучше всего подходит по модулю.

Единственная другая причина вне самой отметки времени - фактическое значение itemId, которое изменяется в каждом запросе. Но если вы делаете это, то действие ожидается и, конечно, создаст новый документ, в котором «комбинация» не существует, потому что именно это и должно быть сделано.

0 голосов
/ 02 мая 2018

Редактировать : Вы на самом деле НЕ НУЖНЫ уникальный индекс для работы upserts, но он все еще рекомендуется, когда вы делаете много upserts и / или коллекция достаточно велика.

Редактировать : Как указал Нил Юнн, вы уже установили секундную часть временной метки на ноль, но забыли сделать то же самое с миллисекундной частью.

Вы должны предоставить уникальное поле для своего upsert, чтобы у MongoDB была возможность найти потенциально существующую запись. Ваши поля itemId и timestamp должны быть помечены как уникальный индекс в коллекции.

В оболочке типа Mongo

db.items.createIndex({"itemId": 1, "timestamp": 1}, {"unique": true})

замените items фактическим названием вашей коллекции.

...