我有两个集合page
和likes
。在两个集合中都有字段pageId
。 likes
也有字段userName
。
如果likes
集合包含pageId
/ userName
对,则表示该页面与特定用户相似。
如何运行一个返回任何一个页面的查询,这个页面不是特定用户喜欢的?
在SQL中,这将是这样的:
SELECT *
FROM page
WHERE NOT EXISTS (SELECT 'a' FROM likes WHERE (likes.pageId = page.pageId) AND (likes.userName = 'userName'))
LIMIT 1
我考虑过使用$exists
运算符但here我已经读过它的含义与具有相同名称的SQL操作不同,我必须使用$in
操作
我可以
page
上运行查询,该查询应返回未包含在列表中的页面。答案 0 :(得分:1)
所以我误解了最初的问题,但要回答,使用MongoDB在单个查询中没有任何方法可以进行该查询。
通常在设置数据时,您不希望像这样规范化数据(针对用户,他们的喜欢和页面的单独集合)。
因此,第一步是根据我们正在寻找的用户获取一个独特的喜欢列表。
db.likes.find({personId: <your_id>}, function(e, allLikes) {/* more */})
获得喜欢之后,您会想要获得唯一的网页ID列表。您可以使用_.uniq()
或在线找到的其他方法来实现此目的。
获得一系列唯一页面_id
后,您现在可以使用$nin
进行查询。
db.pages.find({_id: { $nin: uniquePageIds } }, function(e, allUnlikedPages) { /* your logic */ })
$nin
接受一个数组,并匹配数组中不具有值的任何内容。 You can read here for more details.
答案 1 :(得分:0)
在3.6版本中,我们有一个新的$ lookup管道语法,允许您在相关文档上执行管道。您可以使用它来查找符合您特定条件的相关文档。将其与更多步骤相结合,您可以构建NOT EXISTS查询。
$expr { $and: [] }
将联接与其他约束相结合$limit: 1
进行优化,因为我们只关心是否存在$match
其中,加入属性$exists: false
$project
消除空集合例如,要查询特定用户没有喜欢的页面,请按如下方式构建管道:
db.page.insertOne({ pageId: 1 })
db.page.insertOne({ pageId: 2 })
db.page.insertOne({ pageId: 3 })
db.likes.insertOne({ pageId: 1, userName: "Pinky" })
db.likes.insertOne({ pageId: 2, userName: "Pinky" })
db.likes.insertOne({ pageId: 2, userName: "Brain" })
db.likes.insertOne({ pageId: 3, userName: "Brain" })
db.page.aggregate([{
"$lookup": {
"from": "likes",
"let": {
"pageId": "$pageId"
},
"pipeline": [{
"$match": {
"$expr": {
"$and": [
{ "$eq": [ "$pageId", "$$pageId" ] },
{ "$eq": [ "$userName", "Pinky" ] }
]
}
}
}, {
"$limit": 1
}],
"as": "likes"
}
}, {
"$match": {
"likes.pageId": { "$exists": false }
}
}, {
"$project": {
"likes": false
}
}])