MongoDB计算满足多个条件的深度嵌套元素数量。

huangapple go评论46阅读模式
英文:

mongoDB count deeply nested elements on more then one condition

问题

请帮忙,我需要找到具有以下条件之一的所有_a[]._p[]元素的count():

  1. _a[]._p[].s.d.t[].dateP=2022 并且 _a[]._p[].s.d.t[].tF="N"

  2. _a[]._p[].s.c.t[].dateP=2022 并且 _a[]._p[].s.c.t[].tF="N"

在以下类型的文档中:

{
  "_id": ObjectId("5c05984246a0201286d4b57a"),
  "f": "x",
  "_a": [
    {
      "_p": [
        {
          "pid": 2,
          "s": {
            "d": {
              "t": [
                {
                  "id": 1,
                  "dateP": "20200-09-20"
                },
                {
                  "id": 2,
                  "dateP": "2022-09-20",
                  "tF": "N"
                }
              ]
            },
            "c": {
              "t": [
                {
                  "id": 3,
                  "dateP": "20300-09-22"
                },
                {
                  "id": 4,
                  "dateP": "2022-09-23",
                  "tF": "N"
                }
              ]
            }
          }
        }
      ]
    }
  ]
}

在我的尝试中,我只能计算部分匹配条件的文档,但不确定在有更多嵌套数组的情况下是否正确,并不确定如何更快地计算_a内的_p元素:

db.collection.count({ "_a._p.s.c.t": { $elemMatch: { tF: "N", dateP: /^2022/i } } })

从Playground中预期的结果应如下所示:

{ total: 1 }

因为_a._p具有与上述条件匹配的s.d.t的id:2和s.c.t的id:4。

英文:

Please, help , I need to find count() of all _a[]._p[] elements having at least one of:

_a[]._p[].s.d.t[].dateP=2022 and _a[]._p[].s.d.t[].tF="N"

and

_a[]._p[].s.c.t[].dateP=2022 and _a[]._p[].s.c.t[].tF="N"

in following type of document:

{
"_id": ObjectId("5c05984246a0201286d4b57a"),
f: "x",
"_a": [
  {
    "_p": [
      {
        "pid": 2,
        "s": {
          "d": {
            "t": [
              {
                id: 1,
                "dateP": "20200-09-20",
                
              },
              {
                id: 2,
                "dateP": "2022-09-20",
                "tF": "N"
              }
            ]
          },
          "c": {
            "t": [
              {
                id: 3,
                "dateP": "20300-09-22"
              },
              {
                id: 4,
                "dateP": "2022-09-23",
                "tF": "N"
              }
            ]
          }
        }
      }
    ]
  }
]
}

In my attempt I can count only the documents that partially match the condition , but not sure if this is correct when there is more nested arrays and not sure how to do it faster and count the _p elements inside the _a:

db.collection.count({ "_a._p.s.c.t":{ $elemMatch:{ tF:"N" , dateP: /^2022/i  }  } })

The expected result from playground need to look as follow:

 { total: 1 }

Since the _a._p having s.d.t with id:2 and s.c.t with id:4 match the above condition

Playground

答案1

得分: 1

更新:仅计算元素
db.collection.aggregate([
  {
    $project: {
      sct: {
        "$size": "$_a._p.s.c.t"
      },
      scd: {
        "$size": "$_a._p.s.d.t"
      }
    }
  },
  
])

MONGO_PALYGROUND


<details>
<summary>英文:</summary>

and the solution should be like:

_update: only count element_

db.collection.aggregate([
{
$project: {
sct: {
"$size": "$_a._p.s.c.t"
},
scd: {
"$size": "$_a._p.s.d.t"
}
}
},

])

[MONGO_PALYGROUND](https://mongoplayground.net/p/P8wVsZlIfPD)

</details>



# 答案2
**得分**: 1

这是一个方法,可以在不使用`$unwind`的情况下执行,尽管`$reduce`的嵌套级别似乎非常容易出错。我希望在依赖它之前,你能用大量数据测试它。

```mongodb
db.collection.aggregate([
  {
    "$match": {
      "_a._p.s.d.t": {
        "$elemMatch": {
          "dateP": {"$regex": "^2022"},
          "tF": "N"
        }
      },
      "_a._p.s.c.t": {
        "$elemMatch": {
          "dateP": {"$regex": "^2022"},
          "tF": "N"
        }
      }
    }
  },
  {
    "$project": {
      "ap": "$_a._p"
    }
  },
  {
    "$project": {
      "docCount": {
        "$reduce": {
          "input": "$ap",
          "initialValue": 0,
          "in": {
            "$sum": [
              "$$value",
              {
                "$reduce": {
                  "input": "$$this",
                  "initialValue": 0,
                  "in": {
                    "$sum": [
                      "$$value",
                      {
                        "$cond": [
                          {
                            "$and": [
                              {
                                "$reduce": {
                                  "input": "$$this.s.c.t",
                                  "initialValue": false,
                                  "in": {
                                    "$or": [
                                      "$$value",
                                      {
                                        "$and": [
                                          {"$eq": ["$$this.tF", "N"]},
                                          {
                                            "$regexMatch": {
                                              "input": "$$this.dateP",
                                              "regex": "^2022"
                                            }
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                }
                              },
                              {
                                "$reduce": {
                                  "input": "$$this.s.d.t",
                                  "initialValue": false,
                                  "in": {
                                    "$or": [
                                      "$$value",
                                      {
                                        "$and": [
                                          {"$eq": ["$$this.tF", "N"]},
                                          {
                                            "$regexMatch": {
                                              "input": "$$this.dateP",
                                              "regex": "^2022"
                                            }
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                }
                              }
                            ]
                          },
                          1,
                          0
                        ]
                      }
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    "$group": {
      "_id": null,
      "totalCount": {"$sum": "$docCount"}
    }
  }
])

mongoplayground.net上尝试它。

英文:

Here's one way you can do it without &quot;$unwind&quot;, although the &quot;$reduce&quot; nesting levels seem very error prone. I hope you test this with lots of data before depending on it.

db.collection.aggregate([
  {
    &quot;$match&quot;: {
      &quot;_a._p.s.d.t&quot;: {
        &quot;$elemMatch&quot;: {
          &quot;dateP&quot;: {&quot;$regex&quot;: &quot;^2022&quot;},
          &quot;tF&quot;: &quot;N&quot;
        }
      },
      &quot;_a._p.s.c.t&quot;: {
        &quot;$elemMatch&quot;: {
          &quot;dateP&quot;: {&quot;$regex&quot;: &quot;^2022&quot;},
          &quot;tF&quot;: &quot;N&quot;
        }
      }
    }
  },
  {
    &quot;$project&quot;: {
      &quot;ap&quot;: &quot;$_a._p&quot;
    }
  },
  {
    &quot;$project&quot;: {
      &quot;docCount&quot;: {
        &quot;$reduce&quot;: {
          &quot;input&quot;: &quot;$ap&quot;,
          &quot;initialValue&quot;: 0,
          &quot;in&quot;: {
            &quot;$sum&quot;: [
              &quot;$$value&quot;,
              {
                &quot;$reduce&quot;: {
                  &quot;input&quot;: &quot;$$this&quot;,
                  &quot;initialValue&quot;: 0,
                  &quot;in&quot;: {
                    &quot;$sum&quot;: [
                      &quot;$$value&quot;,
                      {
                        &quot;$cond&quot;: [
                          {
                            &quot;$and&quot;: [
                              {
                                &quot;$reduce&quot;: {
                                  &quot;input&quot;: &quot;$$this.s.c.t&quot;,
                                  &quot;initialValue&quot;: false,
                                  &quot;in&quot;: {
                                    &quot;$or&quot;: [
                                      &quot;$$value&quot;,
                                      {
                                        &quot;$and&quot;: [
                                          {&quot;$eq&quot;: [&quot;$$this.tF&quot;, &quot;N&quot;]},
                                          {
                                            &quot;$regexMatch&quot;: {
                                              &quot;input&quot;: &quot;$$this.dateP&quot;,
                                              &quot;regex&quot;: &quot;^2022&quot;
                                            }
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                }
                              },
                              {
                                &quot;$reduce&quot;: {
                                  &quot;input&quot;: &quot;$$this.s.d.t&quot;,
                                  &quot;initialValue&quot;: false,
                                  &quot;in&quot;: {
                                    &quot;$or&quot;: [
                                      &quot;$$value&quot;,
                                      {
                                        &quot;$and&quot;: [
                                          {&quot;$eq&quot;: [&quot;$$this.tF&quot;, &quot;N&quot;]},
                                          {
                                            &quot;$regexMatch&quot;: {
                                              &quot;input&quot;: &quot;$$this.dateP&quot;,
                                              &quot;regex&quot;: &quot;^2022&quot;
                                            }
                                          }
                                        ]
                                      }
                                    ]
                                  }
                                }
                              }
                            ]
                          },
                          1,
                          0
                        ]
                      }
                    ]
                  }
                }
              }
            ]
          }
        }
      }
    }
  },
  {
    &quot;$group&quot;: {
      &quot;_id&quot;: null,
      &quot;totalCount&quot;: {&quot;$sum&quot;: &quot;$docCount&quot;}
    }
  }
])

Try it [mongoplayground.net](https://mongoplayground.net/p/L760LSbMdZU "Click me!").

huangapple
  • 本文由 发表于 2023年3月3日 23:29:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75629002.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定