{
"_id" : "5955ea4fd8099718330ab191"
lastViewed: [
{
"_id" : ObjectId("595218a7d346d27fb0bc1705"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"groupId" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewedTime" : ISODate("2017-06-19T09:39:07.374Z")
},
{
"_id" : ObjectId("595218a7d346d27fb0bc1764"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"groupId" : ObjectId("5955ea4fd8099718330ab162"),
"lastViewedTime" : ISODate("2017-05-11T09:39:07.374Z")
}
]
}
我想使用$ filter,然后使用$ project值, 我的查询位于userId从params获取的位置
$project: { "viewedDetails": {
"$filter": {
"input": "$lastViewed",
"as": "lastViewed",
"cond": { $and: [{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] }, { "$eq": ["$$lastViewed.groupId", '$_id'] }] }
}
}
}
对于userId 58c796d4344b9da4dfbe027b,我得到了如下的确切输出
{
"_id" : "5955ea4fd8099718330ab191"
viewedDetails: [
{
"_id" : ObjectId("595218a7d346d27fb0bc1705"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"groupId" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewedTime" : ISODate("2017-06-19T09:39:07.374Z")
}
]
}
现在我将我的架构更改为并将$ lookup结果作为
{
"_id" : "5955ea4fd8099718330ab191"
lastViewed: [
{
"_id" : ObjectId("595218a7d346d27fb0bc1705"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"members":[
{
"groupId" : ObjectId("5955ea4fd8099718330ab162"),
"lastViewedTime" : ISODate("2017-05-11T09:39:07.374Z")
}
{
"groupId" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewedTime" : ISODate("2016-05-19T09:39:07.374Z")
}
]
}
]
}
然后我的对象数组的过滤器不起作用,我的查询是
$project: { "viewedDetails": {
"$filter": {
"input": "$lastViewed",
"as": "lastViewed",
"cond": { $and: [{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$eq": ["$$lastViewed.members.groupId", '$_id'] }] }
}
}
},
如何在不使用$ unwind的情况下获得此功能,然后使用$ project。
答案 0 :(得分:3)
不需要$unwind
纯粹用于比较,因为有各种运算符可以通过与列表进行比较来确定逻辑结果。您真的只需更改此处$filter
上的cond
;
过滤“成员”需要使用$map
换行以反映更改:
对于MongoDB 3.4,您可以使用$in
:
"viewedDetails": {
"$map": {
"input": {
"$filter": {
"input": "$lastViewed",
"as": "lastViewed",
"cond": {
"$and": [
{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$in": [ "$_id", "$$lastViewed.members.groupId" ] }
]
}
}
},
"as": "v",
"in": {
"_id": "$$v._id",
"userId": "$$v.userId",
"members": {
"$filter": {
"input": "$$v.members",
"as": "m",
"cond": { "$eq": [ "$$m.groupId", "$_id" ] }
}
}
}
}
}
将值与"$$lastViewed.members.groupId"
返回的数组中的每个值进行比较,并返回true
或false
,具体取决于它是否匹配。
如果您无法使用$in
,则只需将初始$filter
更改为以下某项:
使用预告片$setIsSubset
"cond": {
"$and": [
{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$setIsSubset": [ ["$_id"], "$$lastViewed.members.groupId" ] }
]
}
"cond": {
"$and": [
{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$gt": [
{ "$size": {
"$setIntersection": [
["$_id"],
"$$lastViewed.members.groupId"
]
}},
0
] }
]
}
“cross”导致“set”具有“多于”0
个元素,表示该值存在于同一个引用的数组中。
请注意,在这些表单中,我们将"$_id"
值设为["$_id"]
,因为“集合比较”介于“集合”之间,而不是单个字段。
这是您提供的文档更正文档:
{
"_id" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewed" : [
{
"_id" : ObjectId("595218a7d346d27fb0bc1705"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"members" : [
{
"groupId" : ObjectId("5955ea4fd8099718330ab162"),
"lastViewedTime" : ISODate("2017-05-11T09:39:07.374Z")
},
{
"groupId" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewedTime" : ISODate("2016-05-19T09:39:07.374Z")
}
]
}
]
}
以下是正在运行的管道阶段:
db.collection.aggregate([
{ "$project": {
"viewedDetails": {
"$map": {
"input": {
"$filter": {
"input": "$lastViewed",
"as": "lastViewed",
"cond": {
"$and": [
{ "$eq": [ "$$lastViewed.userId", ObjectId("58c796d4344b9da4dfbe027b") ] },
{ "$in": [ "$_id", "$$lastViewed.members.groupId" ] }
]
}
}
},
"as": "v",
"in": {
"_id": "$$v._id",
"userId": "$$v.userId",
"members": {
"$filter": {
"input": "$$v.members",
"as": "m",
"cond": { "$eq": [ "$$m.groupId", "$_id" ] }
}
}
}
}
}
}}
])
这是输出:
{
"_id" : ObjectId("5955ea4fd8099718330ab191"),
"viewedDetails" : [
{
"_id" : ObjectId("595218a7d346d27fb0bc1705"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"members" : [
{
"groupId" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewedTime" : ISODate("2016-05-19T09:39:07.374Z")
}
]
}
]
}