我想进行一个查询,其中我想要知道用户喜欢或不同于我的状态,现在我想在单个查询上进行,以便我不会从我的NODEJS服务器调用数据库2次,做任何解决了我的问题。
For Add我们正在使用 collection.update({_ id:id}, {$ pull:{ ' user_id':' xxxx-xxxx-xxxx-xxxx' } } );
For Remove我们正在使用
collection.update({ _id: id },
{ $push: {
'user_id': 'xxxx-xxxx-xxxx-xxxx' }
}
);
现在我想在一个查询中同时使用它们,就像在fruit数组中应用present一样,如果不添加则删除它。
答案 0 :(得分:2)
MongoDB不允许$pull
和$push
或任何其他操作在单个语句中更新相同的“路径”(因此是单个数组)。这主要与逻辑处理服务器端有关,其中更新操作从不被视为在语句中进行排序。
示例:
{
"responses": [
{ "user": "Tom", "status": "like" },
{ "user": "Sarah", "status": "unlike" }
]
}
这并不是很有意义,但你不能这样做:
db.collection.update(
{},
{
"$pull": { "responses": { "user": "Tom", "status": "like" },
"$push": { "responses": { "user": "Tom", "status": "unlike" }
}
)
由于此处的单个操作在“响应”的“相同路径”上包含$push
和$pull
。无论你构建语句,都不需要以任何顺序执行。
虽然我们可以“匹配”“Tom”的位置并将其“状态”改为“不同”,但更好的模式是:
{
"likes": ["Tom"],
"unlikes": ["Sarah"],
"likesTotal": 1,
"unlikesTotal": 1,
"totalScore": 0
}
这意味着如果我想更改“Tom”的“投票”,那么您可以在.bind
操作的帮助下创建这样的结构,以启用单个请求和响应:
var bulk = db.collection.initializeOrderedBulkOp();
// Cast "Tom's" unlike where they had a "like" already
bulk.find({
"likes": "Tom",
"unlikes": { "$ne": "Tom" }
}).updateOne({
"$pull": { "likes": "Tom" },
"$push": { "unlikes": "Tom" },
"$inc": {
"likesTotal": -1,
"unlikesTotal": 1
}
]);
// Cast "Tom's" new vote where nothing was there at all
bulk.find({
"unlikes": { "$ne": "Tom" },
"likes": { "$ne": "Tom" }
}).updateOne({
"$push": { "unlikes": "Tom" },
"$inc": {
"unlikesTotal": 1,
"totalScore": -1
}
});
bulk.execute();
这会产生一个非常好的模式。这里的每个更新操作不仅基本上是“原子的”,因为通过对单独的文档属性进行操作,允许每个修饰符执行而不会发生冲突。此外,作为“批量”操作,满足所有可能条件的“两个”更新操作的请求将在单个请求中发送,并在单个响应中接收。
当然,您的“客户端”逻辑还应该知道谁对某个特定项目“喜欢/不喜欢”的当前状态,但在通用API中强制执行此操作是一种很好的做法。
它可以检查数组,并且还可以检查有用的计数器以查找常规数据和一般查询目的,而无需“计算”数组的长度或匹配类型。