我在mongoDB中有这样的json doc:
{ "_id" : ObjectId("57ed88c0965bedd2b11d5727"),
"refid" : 2,
"votes" : [
{ "ip" : "127.0.2.1", "rating" : 5 },
{ "ip" : "127.0.3.1", "rating" : 2 },
{ "ip" : "127.59.83.210", "rating" : 50 },
{ "ip" : "127.56.26.191", "rating" : 5 },
{ "ip" : "127.59.83.210", "rating" : 5 },
{ "ip" : "127.59.83.210", "rating" : 30 }
]
}
而不是为每个IP创建dupes,我想更新IP存在时找到的记录,或者如果不存在则添加新条目。有很多关于如何进行类似操作的问题,但没有一个我能找到这个简单的问题。我在Node.js中尝试这个:
db.collection('ratings').update( { "refid":refid, "votes.ip":ip },
{
$push: { votes: { "ip":ip, "rating":rating }
}
})
但是当我从同一个IP投票时,它只是不断添加新条目。
注意:我没有使用Mongoose。
如果我的问题过于简单,我很抱歉,我对MongoDB很新。我只是想知道是否有一个很好的方法来完成这个,而不是以编程方式迭代“投票”中的每个记录。谢谢!
编辑:我要求的是目前无法解决的问题,我在下面标记了一个正确的答案,其中包含解释以及MongoDB上的故障单链接以进行增强。
至于我在这里提出的问题,下面的代码对我有用。我不知道它在性能方面有多好或多坏,但它涵盖了所有这些场景:
使用:
db.collection('ratings').findOne({ "refid":refid }).then(function(vote) {
if (vote == null) {
newrating = {refid: refid, votes: [{ ip: ip, rating: rating }]};
db.collection('ratings').save(newrating);
} else {
db.collection('ratings').findOne({ "refid":refid, "votes.ip":ip }).then(function(rate) {
if (rate != null) {
db.collection('ratings').update(
{ refid: refid, "votes.ip" : ip },
{ $set: { "votes.$.rating" : rating } }
)
} else {
db.collection('ratings').update({"refid":refid,"votes.ip" : {$ne : ip }},
{ $push: { votes: { "ip" : ip, "rating" : rating, }}}
)
}
})
}
})
答案 0 :(得分:2)
如果不存在则插入文档由upsert完成,如果要更新条件嵌入文档,则需要$ position操作符。因此,您需要在查询中同时使用它们来实现上述功能。
但是现在mongodb不支持使用$ position运算符进行upserting
不要将位置运算符$与upsert运算一起使用,因为, insert将在插入的文档中使用$作为字段名称。
所以你想要的是现在不能在一个查询中做到这一点,或者你可以在两个查询中做到这一点。
首先
db.collection('ratings')).update(
{"refid":refid, "votes.ip": ip},
{
$set: { "votes.$.rating":rating }
}
)
它返回更新的文档数,如果是1则没问题,如果是0,则需要推送新记录。
db.collection('ratings')).update( { "refid":refid, "votes.ip":{$ne: ip}},
{$push: { votes: { "ip":ip , "rating":rating }}
})
还有位置操作员和upserting的jira票,如果你想在mongodb中使用这个功能,请投票支持这个问题。以下是问题链接
答案 1 :(得分:0)
也许
db.collection('ratings').update( { "refid":refid, "ip":ip },
{
$addToSet: { votes: { "ip":ip, "rating":rating }
}
})
答案 2 :(得分:0)
试试这个
db.collection('ratings')).update( { "refid":refid, "votes.ip":ip , "votes.rating":{$ne: rating }},
{$push: { votes: { "ip":ip , "rating":rating }}
})
如果给定的ip不存在评级,它将添加新记录,如果给定的ip和评级存在记录,则不添加重复记录。
答案 3 :(得分:0)
也可以通过这种方式解决。这是我用于工作的那个。
拉出匹配值并按下面所示推送新值:
db.collection(‘ratings’).update({“refid”:refid},
{$pull: {votes: {“ip": ip}}},
{multi: true});
db.collection("ratings").update({“refid":refid},
{$push:{‘votes’:{"ip":ip,"rating":rating}}})
答案 4 :(得分:0)
如果refid存在,则此代码即可完成工作
let bulk = await db.collection('ratings').initializeOrderedBulkOp();
//edit if exist
await bulk.find({ refid: refid, 'votes.ip': ip })
.updateOne({ $set: {'votes.$.rating': rating} });
//add if doesn't exist
await bulk.find({ refid: refid, 'votes.ip': {'$ne': ip} })
.updateOne({ $push: {votes: {ip: ip, rating: rating}} });
await bulk.execute();