如何在条件与数组匹配的地方过滤$ filter? [英] How to $filter where condition is matched against an array?

查看:109
本文介绍了如何在条件与数组匹配的地方过滤$ filter?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在$ 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 进行比较,因为有多种运算符可以通过与清单。您真的只需要在cond rel = nofollow noreferrer>在这里 $ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆