【问题标题】:Query Comparing Arrays of Objects查询比较对象数组
【发布时间】:2017-10-25 06:35:51
【问题描述】:

我想知道如何比较 Mongoose 中的(嵌套)对象数组。

考虑到下面的数据,我想在name 属性匹配时得到结果。谁能帮我解决这个问题?

    Organisation.find( { 
        $or: [ 
          { "category_list": { $in: cat_list } }, 
          { "place_topics.data": { $in: place_tops } } 
        ] 
      } 
    )

假设这是存储在我的 MongoDB 中的数据:

  "category_list": [
      {
          "id": "197750126917541",
          "name": "Pool & Billiard Hall"
      },
      {
          "id": "197871390225897",
          "name": "Cafe"
      },
      {
          "id": "218693881483234",
          "name": "Pub"
      }
  ],
  "place_topics": {
      "data": [
          {
              "name": "Pool & Billiard Hall",
              "id": "197750126917541"
          },
          {
              "name": "Pub",
              "id": "218693881483234"
          }
      ]
  }

假设这些是我要比较的数组(几乎相同的数据):

let cat_list = [
            {
                "id": "197750126917541",
                "name": "Pool & Billiard Hall"
            },
            {
                "id": "197871390225897",
                "name": "Cafe"
            },
            {
                "id": "218693881483234",
                "name": "Pub"
            }
        ]
let place_tops = [
                {
                    "name": "Pool & Billiard Hall",
                    "id": "197750126917541"
                },
                {
                    "name": "Pub",
                    "id": "218693881483234"
                }
            ]

【问题讨论】:

  • 以下是否属实?我们只有在以下情况下才有匹配: - 要比较的数组与它们对应的数组具有相同的长度; - 它们包含相同的 id 集; - id 相同的记录应该有相同的名称,其他字段可以不同。
  • 其实MongoDB中存储的数据也包含一个字符串_id所以是假的。
  • 是的,但是您写道您对比较名称感兴趣,所以我假设您想检查尽管匹配了 id,但名称是否相同(最新或 smth)。看来我误会了你。
  • 没问题,我提供的数据不是实际存储的数据,实际存储的数据更像:{ "_id": { "$oid": "5931bd880472150069e7c" }, "name": "Pool & Billiard Hall" }我应该存储数字 ID,但我没有,所以我必须按名称比较:/

标签: javascript node.js mongodb mongoose mongodb-query


【解决方案1】:

当每个数组元素都需要"multiple conditions" 时,是您实际使用$elemMatch,而实际上“需要”,否则您不匹配正确的元素。

所以要应用多个条件,您宁愿为$or 创建一个条件数组,而不是使用$in 的快捷方式:

Organizations.find({
  "$or": [].concat(
    cat_list.map( c => ({ "category_list": { "$elemMatch": c } }) ),
    place_tops.map( p => ({ "place_topics": { "$elemMatch": p } }) )
  )
})

但是,如果您退后一步并从逻辑上考虑一下,您实际上将属性之一命名为 “id”。这通常意味着在所有良好实践中该值实际上是“唯一的”。

因此,您真正需要做的只是提取这些值并坚持使用原始查询表单:

Organizations.find({
  "$or": [
    { "category_list.id": { "$in": cat_list.map(c => c.id) } },
    { "place_topics.id": { "$in": place_tops.map(p => p.id) } }
  ]
})

因此,只需将值和属性都映射到“匹配”到"id" 值。这是一个简单的"dot notation" 表单,通常在您对每个数组元素有一个条件进行测试/匹配时就足够了。

在给定数据的情况下,这通常是最合乎逻辑的方法,您应该应用其中哪一种方法真正适合您需要的数据条件。对于“多个”,请使用 $elemMatch。但是如果你不需要多个因为有一个单数匹配,那么只需做单数匹配

【讨论】:

  • 这似乎可以解决问题,我将采用最后一种方法,因为在任一语句中都有一个匹配项就足够了。非常感谢!
猜你喜欢
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2016-04-03
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多