如何选择不包含在集合中所有其他文档的数组属性中的文档 ID?

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

How to pick documents id of which is not contained in array property of all other documents in collection?

问题

以下是您要翻译的内容:

我有一组文档,其形式如下:

<!-- 开始代码片段: js 隐藏: false 控制台: true Babel: false -->

<!-- 语言: lang-js -->
const categorySchema = new Schema<ICategory>({
  title: { type: String, required: true },
  children: [{ type: Types.ObjectId, ref: categoryModelName }],
});

<!-- 结束代码片段 -->

我想获取所有文档的ID,这些文档的ID不包含在集合中其他文档的children数组属性中。如果可能的话,该如何编写这样的查询?

英文:

I have collection of documents which has the following shape:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const categorySchema = new Schema&lt;ICategory&gt;({
  title: { type: String, required: true },  
  children: [{ type: Types.ObjectId, ref: categoryModelName }],  
});

<!-- end snippet -->

I want to get all documents id of which is not contained in children array property of all other documents in the collection. How to write such query, if possible?

答案1

得分: 2

你可以编写一个聚合管道:

  1. 进行自我查找并创建一个字段,该字段包含当前文档是其子文档的文档。
  2. 如果子文档数组为空,意味着没有文档是当前文档的子文档。因此,使用匹配来过滤掉这些文档。
db.categoryCollection.aggregate([
  { $lookup: { from: "categoryCollection", localField: "_id", foreignField: "children", as: "childOf" } },
  { $match: { childOf: { $size: 0 } } },
  { $project: { _id: 1 } }
])

playground

英文:

you can write an aggregation pipeline

  1. self lookup and create a field which has documents which the current document is a child of
  2. If a child of array is empty it means there are no documents where the current document is a child. So filter out those using match
db.categoryCollection.aggregate([
  { $lookup: { from: &quot;categoryCollection&quot;, localField: &quot;_id&quot;, foreignField: &quot;children&quot;, as: &quot;childOf&quot; } },
  { $match: { childOf: { $size: 0 } } },
  { $project: { _id: 1 } }
])

playground

答案2

得分: 1

这是另一种方法来做,尽管如果集合非常大,"$group" 阶段可能会超过最大允许的内存。 评论位于聚合管道中。

db.collection.aggregate([
  {
    "$group": {
      // 遍历每个文档
      "_id": null,
      // 将所有 _id 放入数组(已经是唯一的)
      "ids": {"$push": "$_id"},
      // 这将是一个数组的数组,不幸的是
      "children": {"$addToSet": "$children"}
    }
  },
  {
    "$project": {
      // 不需要 _id
      "_id": 0,
      // 将 theIds 分配为输出
      "theIds": {
        // 设置差异 = 在 ids 中但不在 children 中的元素
        "$setDifference": [
          "$ids",
          { // 将 children 折叠为单个平坦数组
            "$reduce": {
              "input": "$children",
              "initialValue": [],
              "in": {"$concatArrays": ["$$value", "$$this"]}
            }
          }
        ]
      }
    }
  }
])

mongoplayground.net 上试试看。

英文:

Here's another way to do it, although if the collection is very large the &quot;$group&quot; stage may exceed the max allowable memory. Comments are in the aggregation pipeline.

db.collection.aggregate([
  {
    &quot;$group&quot;: {
      // go through each document
      &quot;_id&quot;: null,
      // push all _id&#39;s (already unique)
      &quot;ids&quot;: {&quot;$push&quot;: &quot;$_id&quot;},
      // this will be an array of arrays unfortunately
      &quot;children&quot;: {&quot;$addToSet&quot;: &quot;$children&quot;}
    }
  },
  {
    &quot;$project&quot;: {
      // don&#39;t need _id
      &quot;_id&quot;: 0,
      // assign theIds as the output
      &quot;theIds&quot;: {
        // set difference = what&#39;s in ids but not in children
        &quot;$setDifference&quot;: [
          &quot;$ids&quot;,
          { // collapse children to a single flat array
            &quot;$reduce&quot;: {
              &quot;input&quot;: &quot;$children&quot;,
              &quot;initialValue&quot;: [],
              &quot;in&quot;: {&quot;$concatArrays&quot;: [&quot;$$value&quot;, &quot;$$this&quot;]}
            }
          }
        ]
      }
    }
  }
])

Try it on [mongoplayground.net](https://mongoplayground.net/p/sC3FsSGk-UG "Click me!").

huangapple
  • 本文由 发表于 2023年5月11日 00:39:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220792.html
匿名

发表评论

匿名网友

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

确定