mongodb $lookup设置多个join条件, 按数组中某字段值对数据进行排序

先说总结:合理运用mongo的操作符可以实现各类的查询!mongo操作符文档

我有一个商品集合,它包含以下的文档,我需要对他进行分页、排序的查询

{
    "nameCn" : "商品1",
    "prices" : [ 
        {
            "_id" : ObjectId("625ad3faac803944c8d7a6d0"),
            "currency" : "SGD",
            "value" : 10
        }, 
        {
            "_id" : ObjectId("625ad3faac803944c8d7a6d1"),
            "currency" : "MYR",
            "value" : 20
        }
    ],
},
{
    "nameCn" : "商品2",
    "prices" : [ 
        {
            "_id" : ObjectId("625ad3faac803944c8d7a6e4"),
            "currency" : "SGD",
            "value" : 12
        }, 
        {
            "_id" : ObjectId("625ad3faac803944c8d7a6e5"),
            "currency" : "MYR",
            "value" : 22
        }
    ],
}
...

在ui界面会根据用户自身的币种属性显示不同的价格,现在需要根据prices和currency对其进行排序。通过在查询结果中添加一个自定义值realPrice,再由realPrice进行排序即可

{
   $addFields: {
       realPrice: {
         $let: {
           vars: {
             price_1: {
               $arrayElemAt: [
                 {
                   $filter: {
                     input: '$prices',
                     cond: { $eq: ['$$this.currency', user.currency] },
                   },
                 },
                 0,
               ],
             },
           },
           in: '$$price_1.value',
         },
       },
     },
   },
 { $sort: {'realPrice':-1}},
}

这样用户就能看到根据其币种来排序的商品了,但这还没完。我还由一个议价集合,不同的用户对某一些商品存在一个特殊价格。它有这些文档

{
    "currency" : "SGD",
    "price" : 230,
    "user" : ObjectId("625d31774525bc4c21c6ac89"),
    "good" : ObjectId("6260d5507e8392e6b44ef235"),
},
{
    "currency" : "SGD",
    "price" : 330,
    "user" : ObjectId("625d31774525bc4c21c6ac89"),
    "good" : ObjectId("625ad3faac803944c8d7a729"),
}
...

此时我的商品列表的查询变得相当复杂,在查询用户看到的商品价格列表时,需要先匹配到议价表中对应的用户商品价格,通过操作符pipeline来对需要lookup的集合匹配多个条件。

再添加realPrice字段进行排序,当商品存在该用户的议价时则显示议价价格,不存在则显示公用价格,此时的排序需求就变的更加复杂了,实现结果如下

{
  $lookup: {
    from: 'pricebargain',
    let: {
      good: '$_id',
    },
    pipeline: [
      {
        $match: {
          $expr: {
            $and: [
              {
                $eq: ['$good', '$$good'],
              },
            ],
          },
          user: ObjectID(user._id),
        },
      },
    ],
    as: 'priceBargainInfo',
  },
},
{
  $unwind: {
    path: '$priceBargainInfo',
    preserveNullAndEmptyArrays: true,
  },
},
{
   $addFields: {
     realPrice: {
       $let: {
         vars: {
           price_1: '$priceBargainInfo.price',
           price_2: {
             $arrayElemAt: [
               {
                 $filter: {
                   input: '$prices',
                   cond: { $eq: ['$$this.currency', user.currency] },
                 },
               },
               0,
             ],
           },
         },
         in: { $cond: ['$$price_1', '$$price_1', '$$price_2.value'] },
       },
     },
   },
 }

先得到用户的议价信息,注入到price_1中,在匹配商品对应用户币种的价格,注入到price_2中,最终通过mongo提供的$cond三目运算符,来决定最终应用的价格。这样就能实现我们的排序效果了。

mongo还有很多好用的操作符,养成学习阅读官方文档的习惯,遇到新的需求就能快速解决啦~

你可能感兴趣的:(后端,node,mongodb,node.js)