如何在条件与数组匹配的地方过滤$ filter? [英] How to $filter where condition is matched against an array?
问题描述
在$ lookup之后,我将得到一个名为lastViewed的联接,如下所示:
after $lookup i will get a join named lastViewed like this:
{
"_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从参数获取的位置以下
I want to use $filter and then $project values , my query is below where the userId is getting from params
$project: { "viewedDetails": {
"$filter": {
"input": "$lastViewed",
"as": "lastViewed",
"cond": { $and: [{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] }, { "$eq": ["$$lastViewed.groupId", '$_id'] }] }
}
}
}
我获得了userId 58c796d4344b9da4dfbe027b
I got the exact output as below for userId 58c796d4344b9da4dfbe027b
{
"_id" : "5955ea4fd8099718330ab191"
viewedDetails: [
{
"_id" : ObjectId("595218a7d346d27fb0bc1705"),
"userId" : ObjectId("58c796d4344b9da4dfbe027b"),
"groupId" : ObjectId("5955ea4fd8099718330ab191"),
"lastViewedTime" : ISODate("2017-06-19T09:39:07.374Z")
}
]
}
现在我将架构更改为$ lookup结果
Now i changed my schema into and got $lookup result as
{
"_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")
}
]
}
]
}
然后我的对象数组过滤器不起作用,我的查询是
then my filter for array of objects is not working , my query is
$project: { "viewedDetails": {
"$filter": {
"input": "$lastViewed",
"as": "lastViewed",
"cond": { $and: [{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$eq": ["$$lastViewed.members.groupId", '$_id'] }] }
}
}
},
如何在不使用$ unwind然后使用$ project的情况下获取此信息。
How can i get this without using $unwind, then using $project.
推荐答案
完全没有必要进行 $ unwind
进行比较,因为有多种运算符可以通过与清单。您真的只需要在 $ filter
;
There is no need to $unwind
purely for comparison, since there are various operators which can determine a logical result by comparing to a list. You really only need change the cond
on the $filter
here;
过滤成员需要换行与 $ map
来反映更改:
Filtering the "members" requires wrapping with $map
to reflect the change though:
对于MongoDB 3.4,您可以使用 $ in
:
For MongoDB 3.4 you can use $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
取决于是否匹配。
Which compares the value against each of the values in the array returned by "$$lastViewed.members.groupId"
and returns true
or false
depending on if it is a match.
如果不能使用 $ in
,然后只有初始的 $ filter
需要更改为以下值之一:
If you cannot use $in
then only the initial $filter
need change to one of the following:
比使用taler更容易 $ setIsSubse t
Eariler than tat use $setIsSubset
"cond": {
"$and": [
{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$setIsSubset": [ ["$_id"], "$$lastViewed.members.groupId" ] }
]
}
或甚至 $ setIntersection
和 $ size
"cond": {
"$and": [
{ "$eq": ["$$lastViewed.userId", mongoose.Types.ObjectId(userId)] },
{ "$gt": [
{ "$size": {
"$setIntersection": [
["$_id"],
"$$lastViewed.members.groupId"
]
}},
0
] }
]
}
其中交集导致具有多个 0
元素的集合意味着该值存在于同一引用数组中。
Where the "intersection" resulting in a "set" that has "more than" 0
elements means that the value was present within the same referenced array.
请注意,在这些表格中,我们将 $ _ id
的值设置为 [ $ _ id]
,因为集合比较位于集合之间,而不是单个字段之间。
Note that in those forms we make the "$_id"
value an array as ["$_id"]
since the "set comparison" is between "sets" and not an individual field.
这是您提供的语法更正文档:
This is the document you provided with corrections to syntax:
{
"_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")
}
]
}
]
}
这是正在运行的管道阶段:
Here is the pipeline stage being run:
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")
}
]
}
]
}
这篇关于如何在条件与数组匹配的地方过滤$ filter?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!