mongodb Mongoose $将嵌套数组与查询值匹配或返回所有文档

ufj5ltwl  于 2023-10-16  发布在  Go
关注(0)|答案(2)|浏览(129)

主要任务:为产品应用标签过滤器(可以是一个或多个)。
需要返回过滤后的产品列表与指定的饮食标签查询。产品标签字段是对标签集合的引用。
$lookup和相关阶段:

{
  $lookup: {
    from: 'tags',
    localField: 'tags',
    foreignField: '_id',
    as: 'tags',
    pipeline: [
      {
        $project: {
          tags: '$tags',
          _id: 0,
        },
      },
    ],
  },
},
{ $unwind: { path: '$tags', preserveNullAndEmptyArrays: true } },
{
  $addFields: {
    tags: '$tags.tags',
  },
},

如果tags集合有ref tags id,则输出产品。否则标签字段不存在。

{
  "_id": "65543472bde41c7561151fd3",
  "slug": "green-olives",
  "name": "Green Olives",
  "description": "Some description",
  "category": "food-cupboard",
  "subCategory": "canned-vegetables"
  "popularity": 76,
  "views": 327,
  "rating": 5,
  "tags": {
    "dietaries": [
      "HALAL"
    ],
    "promotions": [
      "PWP"
    ]
  },
}

预期的(虚拟的)聚合$match阶段:

{
  $match: {
    // if query "tags" exist => filter products which have (tags.dietaries) with query values
    // if query "tags" doesn't exist => all product with tags field and without it
  }
}

尝试用正则表达式匹配'tags.dietaries'数组,如果dietary(查询)存在,否则返回所有。问题是产品返回,但只有现有的标签字段。

{
  $match: {
    'tags.dietaries': dietary
      ? {
          $regex: dietary.split('+').join('|'),
        }
      : /.*/,
  },
},

另一个想法是使用$cond运算符,但不能正确应用它。
此外,我还认为默认情况下保持标签字段为空,这样就可以/改进匹配标签。这是个好主意吗
如果能帮上忙我会很感激的。

ahy6op9u

ahy6op9u1#

根据我的理解,我做了这个聚合,
我冒昧地删除了放松阶段,因为我没有看到它的用途,我注意到,你有一个一对一的关系,所以我只是采取了第一个项目。
如果我正确理解了你的过滤标准,你想通过dietaries过滤,如果标签可用,如果不只是返回所有内容,
我希望我的理解是对的,如果不给我留下一些评论,所以我们可以调整聚合。

[{
    "$lookup": {
      "from": "tags",
      "localField": "tags",
      "foreignField": "_id",
      "as": "tags"
    }
  },
  {
    "$addFields": {
      "tags": {
        "$arrayElemAt": [
          "$tags.tags",
          0
        ]
      }
    }
  },
  {
    "$addFields": {
      "dietariesIntersectionSize": {
        "$size": {
          "$ifNull": [{
              "$setIntersection": [
                /// the array of the query
                [
                  "HALAL",
                  "GLUTEN_FREE"
                ],
                "$tags.dietaries"
              ]
            },
            []
          ]
        }
      }
    }
  },
  {
    "$match": {
      "$or": [{
          "tags": {
            "$eq": null
          }
        },
        {
          "dietariesIntersectionSize": {
            "$gt": 0
          }
        }
      ]
    }
  }

]

我希望这对你有帮助

z2acfund

z2acfund2#

看起来像拐杖,但工作正常。

{
 $match: {
  'tags.dietaries': {
    $in: dietary ? dietary.split('+') : [null, /.*/],
  },
 },
},

产品描述:
1.如果查询存在('HALAL +GLUTEN_FREE'),则返回'tags.dietaries'标签数组包含查询标签数组之一的文档:$in: dietary ? dietary.split('+')
1.否则返回'tags.dietaries'字段存在但不存在的文档:: [null, /.*/]
谢谢Abdellatif Sraiti的帮助。他把我带到了正确的方向。
希望能帮助别人。
P.S.如果有人能分享一个更好的解决方案,我将不胜感激。

相关问题