Mongoose:如果值存在于对象数组中的数组中,则过滤数据

Posted

技术标签:

【中文标题】Mongoose:如果值存在于对象数组中的数组中,则过滤数据【英文标题】:Mongoose: filter data if value exists in array within array of objects 【发布时间】: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"
        ],
    
]

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

【问题讨论】:

【参考方案1】:

这就是你要找的东西。

[
  
    $unwind: "$services"
  ,
  
    $match: 
      "services.categories": "SD-WAN"
    
  ,
  
    $group: 
      _id: "$_id",
      active: 
        $first: "$active"
      ,
      name: 
        $first: "$name"
      ,
      contacts: 
        $first: "$contacts"
      ,
      services: 
        $addToSet: "$services"
      
    
  
]
    使用$unwind 来展平数组 使用$match进行过滤 使用$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 来做到这一点?

以上是关于Mongoose:如果值存在于对象数组中的数组中,则过滤数据的主要内容,如果未能解决你的问题,请参考以下文章

如果不存在,Mongoose 将多个对象添加到数组

检查对象值是不是存在于 Javascript 对象数组中,如果不存在则将新对象添加到数组

如果不存在,Mongoose会将多个对象添加到数组中

Mongoose 嵌套对象数组中的唯一值

Mongoose 嵌套对象数组中的唯一值

如果未找到值,则使用 mongoose 将对象添加到数组中,否则更新字段