我有两个收藏page
和likes
。在这两个集合中都有 field 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
Run Code Online (Sandbox Code Playgroud)
我想过使用该$exists
运算符,但在这里我读到它的含义与同名的 SQL 操作不同,我必须使用该$in
运算符。
我可以
page
,这应该返回第一个页面,该页面不包含在列表中。我正在犹豫是否以这种方式实现它,因为它对我来说似乎效率很低(我在步骤 2 中只需要一页,但为了获得该一页,我需要遍历用户的所有喜欢)。
在 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
}
}])
Run Code Online (Sandbox Code Playgroud)
所以我误读了最初的问题,但要回答,没有任何方法可以使用 MongoDB 在单个查询中执行该查询。
通常,在设置数据时,您不希望像这样标准化数据(用户、他们的喜好和页面的单独集合)。
因此,第一步是根据我们正在寻找的用户获取唯一的喜欢列表。
db.likes.find({personId: <your_id>}, function(e, allLikes) {/* more */})
Run Code Online (Sandbox Code Playgroud)
获得点赞后,您将需要获得唯一的页面 ID 列表。您可以使用_.uniq()
网上找到的方法或其他方法来做到这一点。
一旦获得唯一 page 的数组_id
,您现在就可以使用 进行查询$nin
。
db.pages.find({_id: { $nin: uniquePageIds } }, function(e, allUnlikedPages) { /* your logic */ })
Run Code Online (Sandbox Code Playgroud)
$nin
接受一个数组,并将匹配具有不在数组中的值的任何内容。 您可以阅读此处了解更多详细信息。
归档时间: |
|
查看次数: |
17302 次 |
最近记录: |