MongoDB – 从先前匹配的文档中聚合匹配字段

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

MongoDB - aggregate match field from the previously matched document

问题

我有一个具有以下架构的集合 -

    const ContentSchema = new Schema({
        label: {
            type: String
        },
        itemId: {
            type: Schema.ObjectId,
            refPath: 'onModel'
        },
        formId: {
            type: Schema.ObjectId,
            refPath: 'onModel'
        },
        value: {
            type: Schema.Types.Mixed,
            index: "text"
        },
    }, { timestamps: true, versionKey: false });

以下是该集合可能包含的一些示例文档 -

    {
      _id: ObjectId('647b1538c29a553ad6e8f316'),
      label: "Name",
      itemId: ObjectId('647b1538c29a553ad6e8f313'),
      formId: ObjectId('647b1538c29a553ad6e8f913'),
      value: "ABC"
    },
    {
      _id: ObjectId('647b1538c29a553ad6e8f416'),
      label: "Email",
      itemId: ObjectId('647b1538c29a553ad6e8f313'),
      formId: ObjectId('647b1538c29a553ad6e8f913'),
      value: "def@mail.com"
    },
    {
      _id: ObjectId('647b1538c29a553ad6e8f516'),
      label: "Name",
      itemId: ObjectId('647b1538c29a553ad6e8f320'),
      formId: ObjectId('647b1538c29a553ad6e8f913'),
      value: "MNO"
    },
    {
      _id: ObjectId('647b1538c29a553ad6e8f616'),
      label: "Email",
      itemId: ObjectId('647b1538c29a553ad6e8f320'),
      formId: ObjectId('647b1538c29a553ad6e8f913'),
      value: "xyz@mail.com"
    }

现在,我需要执行一个查询来从具有formIdObjectId('647b1538c29a553ad6e8f913')的集合中搜索"ABC"。

以下是执行此操作的代码 -

    return await ContentModel.aggregate([
    {
        $match: {
            $text: { $search: text },
            formId: new mongoose.Types.ObjectId(formId)
        }
    }]

上面的代码完全正常工作,并返回文档 -

    {
        _id: ObjectId('647b1538c29a553ad6e8f316'),
        label: "Name",
        itemId: ObjectId('647b1538c29a553ad6e8f313'),
        formId: ObjectId('647b1538c29a553ad6e8f913'),
        value: "ABC"
    }

但我需要在同一聚合中获取更多记录。现在我需要查找具有itemId为ObjectId('647b1538c29a553ad6e8f313')的文档中的其他文档。

因此,聚合现在应该返回2个文档 -

        {
          _id: ObjectId('647b1538c29a553ad6e8f316'),
          label: "Name",
          itemId: ObjectId('647b1538c29a553ad6e8f313'),
          formId: ObjectId('647b1538c29a553ad6e8f913'),
          value: "ABC"
        },
        {
          _id: ObjectId('647b1538c29a553ad6e8f416'),
          label: "Email",
          itemId: ObjectId('647b1538c29a553ad6e8f313'),
          formId: ObjectId('647b1538c29a553ad6e8f913'),
          value: "def@mail.com"
        }

我尝试使用以下查询,但不起作用 -

    return await ContentModel.aggregate([
    {
        $match: {
            $text: { $search: text },
            formId: new mongoose.Types.ObjectId(formId)
        }
    },
    {
        $match: { itemId: "$itemId" }
    }]
英文:

I have a collection with following schema -

const ContentSchema = new Schema({
    label: {
        type: String
    },
    itemId: {
        type: Schema.ObjectId,
        refPath: 'onModel'
    },
    formId: {
        type: Schema.ObjectId,
        refPath: 'onModel'
    },
    value: {
        type: Schema.Types.Mixed,
        index: "text"
    },
}, { timestamps: true, versionKey: false });

Here are some example documents the collection may have -

{
  _id: ObjectId('647b1538c29a553ad6e8f316'),
  label: "Name",
  itemId: ObjectId('647b1538c29a553ad6e8f313'),
  formId: ObjectId('647b1538c29a553ad6e8f913'),
  value: "ABC"
},
{
  _id: ObjectId('647b1538c29a553ad6e8f416'),
  label: "Email",
  itemId: ObjectId('647b1538c29a553ad6e8f313'),
  formId: ObjectId('647b1538c29a553ad6e8f913'),
  value: "def@mail.com"
},
{
  _id: ObjectId('647b1538c29a553ad6e8f516'),
  label: "Name",
  itemId: ObjectId('647b1538c29a553ad6e8f320'),
  formId: ObjectId('647b1538c29a553ad6e8f913'),
  value: "MNO"
},
{
  _id: ObjectId('647b1538c29a553ad6e8f616'),
  label: "Email",
  itemId: ObjectId('647b1538c29a553ad6e8f320'),
  formId: ObjectId('647b1538c29a553ad6e8f913'),
  value: "xyz@mail.com"
}

Now, I need to perform a query to search "ABC" from the collection with formId - ObjectId('647b1538c29a553ad6e8f913').

Here is the code to do that -

return await ContentModel.aggregate([
{
    $match: {
        $text: { $search: text },
        formId: new mongoose.Types.ObjectId(formId)
    }
}]

The above code is absolutely working fine and returns the document -

{
    _id: ObjectId('647b1538c29a553ad6e8f316'),
    label: "Name",
    itemId: ObjectId('647b1538c29a553ad6e8f313'),
    formId: ObjectId('647b1538c29a553ad6e8f913'),
    value: "ABC"
}

But I need more records within the same aggregation. Now I need to find out other documents from the document with itemId - ObjectId('647b1538c29a553ad6e8f313').

So that the aggregation should now return 2 documents -

    {
      _id: ObjectId('647b1538c29a553ad6e8f316'),
      label: "Name",
      itemId: ObjectId('647b1538c29a553ad6e8f313'),
      formId: ObjectId('647b1538c29a553ad6e8f913'),
      value: "ABC"
    },
    {
      _id: ObjectId('647b1538c29a553ad6e8f416'),
      label: "Email",
      itemId: ObjectId('647b1538c29a553ad6e8f313'),
      formId: ObjectId('647b1538c29a553ad6e8f913'),
      value: "def@mail.com"
    }

I am trying with following query which does not work -

return await ContentModel.aggregate([
{
    $match: {
        $text: { $search: text },
        formId: new mongoose.Types.ObjectId(formId)
    }
},
{
    $match: { itemId: "$itemId" }
}]

答案1

得分: 0

如果我理解正确,您可以按以下方式在自己的集合中使用 $lookup

在这个查询中,您可以像您已经做的那样使用 $match,然后使用匹配的结果进行 $lookup(类似于 SQL 中的 JOIN),针对您的数据使用 collection 和匹配的 itemId

所以就像是说“将匹配的 itemId 与所有其他 itemId 进行关联”。我认为这就是您想要的。

db.collection.aggregate([
  {
    "$match": { /* 您的匹配条件 */ }
  },
  {
    "$lookup": {
      "from": "collection",
      "localField": "itemId",
      "foreignField": "itemId",
      "as": "results"
    }
  },
  {
    "$unwind": "$results"
  },
  {
    "$replaceRoot": {
      "newRoot": "$results"
    }
  }
])

此外,另外两个步骤是将结果输出为根。

示例在这里

英文:

If I've understood correctly you can use $lookup with your own collection in this way:

In this query you can $match as you have done and then, with matching results you can $lookup (like a SQL JOIN) against your data using collection and matching itemId.

So is like to say "join the matching itemId with all others itemId". And I think is what you want.

db.collection.aggregate([
  {
    "$match": { /* your match*/ }
  },
  {
    "$lookup": {
      "from": "collection",
      "localField": "itemId",
      "foreignField": "itemId",
      "as": "results"
    }
  },
  {
    "$unwind": "$results"
  },
  {
    "$replaceRoot": {
      "newRoot": "$results"
    }
  }
])

Also the two others steps are to output the result as root.

Example here

huangapple
  • 本文由 发表于 2023年6月8日 22:02:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/76432683.html
匿名

发表评论

匿名网友

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

确定