MongoDB:只投影数组中被查询到的项目?

问题描述 投票:0回答:1

我有一个用户文档,每个用户都有一个对象数组,给定一个项目标签数组,我需要找到项目数组中有项目标签的用户,并返回整个用户对象。除了 数组中,我只想返回存在于项目列表中的第一个项目标签。tagArray 是用于初始查询的。

//user document
 {
    user: 'John',
    items: [ObjectId('ABC'), ObjectId('123') ...]
 }

//item document
{
  _id: ObjectId('ABC'),
  tag: 'some-unique-id'
}, 
{
  _id: ObjectId('DEF'),
  tag: 'some-unique-tag'
}

用户与项目之间是1对N的关系,项目可以在用户的项目数组中重复。

这就是我目前的情况,它不仅返回整个用户对象,而且还返回数组内的所有项目。

const tagArray = [ 'some-unique-id', 'some-unique-tag']
items.aggregate([
  { $match: { 'tag': { $in: tagArray } }},
  { $lookup: {
        from: "users",
        localField: "tag",
        foreignField: '_id',
        as: 'userInfo'
       }
  },
  {
     $project: {??}  //<--- I'm pretty sure I'm missing something in the project
])

我现在的结果。

{
 _id: ObjectId('ABC'),
  tag: 'some-unique-id'
  userInfo : [ {user: 'John', items: [ObjectId('ABC'), ObjectId('123') ...] }]
}

我想达到的目标。

{
 _id: ObjectId('ABC'),
  tag: 'some-unique-id'
  userInfo : [ {user: 'John', items: [ObjectId('ABC')]} ]
}

编辑:这里有一个类似的问题: 在MongoDB集合中,只检索对象数组中的被查询元素。

然而,在我的例子中,我需要的过滤条件是 "标签中的一个标签是在 tagArray.

如果有任何建议或指点,将不胜感激,谢谢!

javascript arrays node.js mongodb projection
1个回答
0
投票

我不知道我是否理解你的需求,但我认为这是一个好的开始(也许你可以自己修改)。

测试数据:

 // users collection
  [
    {
      user: "John",
      items: [
        ObjectId("5a934e000102030405000002"),
        ObjectId("5a934e000102030405000003")
      ]
    }
  ]  

 // items collection
  [
    {
      _id: ObjectId("5a934e000102030405000002"),
      tag: "some-unique-id"
    },
    {
      _id: ObjectId("5a934e000102030405000009"),
      tag: "some-unique-tag"
    }
  ]
}

查询:

db.users.aggregate([
  {
    $lookup: {
      from: "items",
      localField: "items",
      foreignField: "_id",
      as: "userInfo"
    }
  },
  // create new fields inside the userInfo array
  {
    $project: {
      "userInfo.user": "$user",
      "userInfo.items": "$items",
      "tag": {
        $arrayElemAt: ["$userInfo.tag", 0]
      }
    }
  },
  // filter the userInfo.items field, based on _id field
  // it's important to use $arrayElemAt here 
  {
    $addFields: {
      "userInfo.items": {
        $filter: {
          input: {
            $arrayElemAt: [
              "$userInfo.items",
              0
            ]
          },
          as: "i",
          cond: {   
            $in: [
              "$$i",
              [
                "$_id" 
              ]
            ]
          }
        }
      }
    }
  }
])

结果:

[
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "tag": "some-unique-id",
    "userInfo": [
      {
        "items": [
          ObjectId("5a934e000102030405000002")
        ],
        "user": "John"
      }
    ]
  }
]
© www.soinside.com 2019 - 2024. All rights reserved.