mongodb 如果存在则递增,否则插入
mongodb increment if exists otherwise insert
在下面的代码中,如果 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 );
}
});
它最终创建了多个文档。提前谢谢你。
编辑:你实际上不需要唯一索引来让upserts工作,但是当你做很多upserts时仍然推荐它and/or collection 挺大的。
Edit:正如 Neil Yunn 所指出的,您已经将时间戳的 seconds-part 设置为零,但忘记对 milliseconds-part.
您应该为您的 upsert 提供一个唯一字段,以便 MongoDB 有机会找到可能存在的记录。您的字段 itemId
和 timestamp
应在 collection.
中标记为唯一索引
在Mongoshell中输入
db.items.createIndex({"itemId": 1, "timestamp": 1}, {"unique": true})
将 items
替换为您 collection 的真实姓名。
您仍然有毫秒部分(或者至少它会以这种方式显示),因此只要该部分在当前分钟内是唯一的,这仍将插入一个新文档。
这是您的代码,它错误地保留了毫秒数:
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>
因此,当日期实际四舍五入到您预期的 "minute" 时,就没问题了。
这里的底线是 "upsert" 仅在提供的条件(本质上是文档的 "key" )实际上不匹配任何现有文档时才会出现,因此有些东西明显不同每个请求和最有可能的候选人是您代码中的 timestamp
值及其后续转换。
也就是说,除非您实际上是从外部或已经定义的来源读取 timestamp
,否则获得 "current time" 的最佳方法是简单地使用普通的 Date
方法:
var timestamp = Date.now();
timestamp = timestamp - ( timestamp % ( 1000 * 60 ) );
console.log(new Date(timestamp));
这应该可以完成这项工作,而无需弄乱其他导入的库。
所以你真的应该看看为什么你有你当前的代码,如果你正在读取一个已经定义的值那么实际上 "ensure" 毫秒和秒在四舍五入中被删除,就像模方法通常做的那样最好的。
除时间戳本身之外的唯一其他原因是每个请求中更改的实际 itemId
值。但是,如果您这样做,那么该操作是预期的,并且当然会创建一个新文档,其中 "combination" 不存在,因为这就是它的目的。
在下面的代码中,如果 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 );
}
});
它最终创建了多个文档。提前谢谢你。
编辑:你实际上不需要唯一索引来让upserts工作,但是当你做很多upserts时仍然推荐它and/or collection 挺大的。
Edit:正如 Neil Yunn 所指出的,您已经将时间戳的 seconds-part 设置为零,但忘记对 milliseconds-part.
您应该为您的 upsert 提供一个唯一字段,以便 MongoDB 有机会找到可能存在的记录。您的字段 itemId
和 timestamp
应在 collection.
在Mongoshell中输入
db.items.createIndex({"itemId": 1, "timestamp": 1}, {"unique": true})
将 items
替换为您 collection 的真实姓名。
您仍然有毫秒部分(或者至少它会以这种方式显示),因此只要该部分在当前分钟内是唯一的,这仍将插入一个新文档。
这是您的代码,它错误地保留了毫秒数:
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>
因此,当日期实际四舍五入到您预期的 "minute" 时,就没问题了。
这里的底线是 "upsert" 仅在提供的条件(本质上是文档的 "key" )实际上不匹配任何现有文档时才会出现,因此有些东西明显不同每个请求和最有可能的候选人是您代码中的 timestamp
值及其后续转换。
也就是说,除非您实际上是从外部或已经定义的来源读取 timestamp
,否则获得 "current time" 的最佳方法是简单地使用普通的 Date
方法:
var timestamp = Date.now();
timestamp = timestamp - ( timestamp % ( 1000 * 60 ) );
console.log(new Date(timestamp));
这应该可以完成这项工作,而无需弄乱其他导入的库。
所以你真的应该看看为什么你有你当前的代码,如果你正在读取一个已经定义的值那么实际上 "ensure" 毫秒和秒在四舍五入中被删除,就像模方法通常做的那样最好的。
除时间戳本身之外的唯一其他原因是每个请求中更改的实际 itemId
值。但是,如果您这样做,那么该操作是预期的,并且当然会创建一个新文档,其中 "combination" 不存在,因为这就是它的目的。