【问题标题】:Mongoose: filter data if value exists in array within array of objectsMongoose:如果值存在于对象数组中的数组中,则过滤数据
【发布时间】:2020-11-19 22:00:33
【问题描述】:

我有一个使用 Aggregate 的工作 mongoose 查询,我根据对象数组中的值过滤数据,但由于需求变化而遇到麻烦。

这是我的数据在 MongoDB 中的样子(它已经填充了虚拟数据)

{
"_id" : ObjectId("5ef44528af5a1a2a641cd52b"),
"active" : true,
"name" : "CompanyA",
"contacts" : [ 
    {
        "secondary_emails" : [],
        "_id" : ObjectId("5f19727495f4da29403923e3"),
        "email" : "contact@gmail.com",
        "designation" : "VP Cloud & Security",
        "address" : "",
        "name" : "Ron"
    }
],
"services" : [ 
    {
        "active" : true,
        "_id" : ObjectId("5ef44528af5a1a2a641cd52d"),
        "name" : "Company Management",
        "title" : "Company Helpline",
        "description" : "Offering voice, meetings, collaboration and contact center all on one cloud platform.",
        "categories" : [ 
            "SD-WAN", 
            "Security and Compliance"
        ],
        "sub_categories" : [ 
            "Solution"
        ],
    },
    {
      "active" : true,
      "_id" : ObjectId("5ef44528af5a1a2a641cd52c"),
      "name" : "Company HR",
      "title" : "Human Resources",
      "description" : "Offering HR Services to all",
      "categories" : [ 
          "HR", "Company"
      ],
      "sub_categories" : [ 
          "Solution"
      ],
  }
]}

目标:根据用户提供的类别(假设其“SD-WAN”)过滤服务,之前类别是单数,现在是一组值,因为一个服务可以属于多个类别

以前的解决方案 我用于奇异类别值的猫鼬查询如下:

db.Collection("suppliers").aggregate([
  {
    $project: {
      services: {
        $filter: {
          input: "$services",
          as: "services",
          cond: { $eq: ["$$services.category", "SD-WAN" ] },
        },
      },
    },
  },
  { $match: { services: { $exists: true, $not: { $size: 0 } } } },
]);

我在尝试在 $$services.categories 中搜索 SD-WAN 时遇到问题,这是一个值数组。有没有办法更新上述查询以使用 $eq 管道运算符或其他解决方案搜索 services.categories 数组中的值。

预期结果

"_id" : ObjectId("5ef44528af5a1a2a641cd52b"),
"services" : [ 
    {
        "active" : true,
        "_id" : ObjectId("5ef44528af5a1a2a641cd52d"),
        "name" : "Company Management",
        "title" : "Company Helpline",
        "description" : "Offering voice, meetings, collaboration and contact center all on one cloud platform.",
        "categories" : [ 
            "SD-WAN", 
            "Security and Compliance"
        ],
        "sub_categories" : [ 
            "Solution"
        ],
    }
]

如果有人能帮助我解决这个问题,我将不胜感激。如果需要更多信息,请询问。谢谢。

【问题讨论】:

    标签: node.js mongodb mongoose aggregation-framework mongoose-schema


    【解决方案1】:

    这就是你要找的东西。

    [
      {
        $unwind: "$services"
      },
      {
        $match: {
          "services.categories": "SD-WAN"
        }
      },
      {
        $group: {
          _id: "$_id",
          active: {
            $first: "$active"
          },
          name: {
            $first: "$name"
          },
          contacts: {
            $first: "$contacts"
          },
          services: {
            $addToSet: "$services"
          }
        }
      }
    ]
    
    1. 使用$unwind 来展平数组
    2. 使用$match进行过滤
    3. 使用$group 将其分组。

    我们仅扁平化服务。这就是为什么我使用$addToSet

    工作Mongo playground

    【讨论】:

    • 感谢您的快速回复,完美解决了我的问题!
    • $first 做什么?
    • 当我们展开时,可能会出现数组(“服务”)大小的重复项。所以当我们对它进行分组时,我们只需要第一个对象,因为其他对象是重复的docs.mongodb.com/manual/reference/operator/aggregation/first
    【解决方案2】:

    这是另一种不使用聚合的方法 游乐场链接:https://mongoplayground.net/p/jmLghGBXb7f

    db.collection.find({
      "services": {
        $elemMatch: {
          categories: {
            $regex: "SD-WAN",
            $options: "i"
          }
        }
      }
    },
    {
      "services": {
        $elemMatch: {
          categories: {
            $regex: "SD-WAN",
            $options: "i"
          }
        }
      }
    })
    

    输出:

    [
      {
        "_id": ObjectId("5ef44528af5a1a2a641cd52b"),
        "services": [
          {
            "_id": ObjectId("5ef44528af5a1a2a641cd52d"),
            "active": true,
            "categories": [
              "SD-WAN",
              "Security and Compliance"
            ],
            "description": "Offering voice, meetings, collaboration and contact center all on one cloud platform.",
            "name": "Company Management",
            "sub_categories": [
              "Solution"
            ],
            "title": "Company Helpline"
          }
        ]
      }
    ]
    

    【讨论】:

    • 这个查询部分起作用,因为它只会返回它找到的第一个类别为SD-WAN的服务,同一类别可以有多个服务。查询应过滤具有该类别的服务。有没有办法使用 find 来做到这一点?
    猜你喜欢
    • 2019-07-14
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多