【问题标题】:Mongo DB How to find common in two arrays and sort in descending order in a single queryMongodb如何在单个查询中找到两个数组中的共同点并按降序排序
【发布时间】:2020-03-28 15:09:48
【问题描述】:

这是我保存在数据库中的数据

0  _id:5e4d18bd10e5482eb623c6e4
   name:'John singh',
   cars_owned:[
       {car_id:'1'},
       {car_id:'5'},
       {car_id:'7'},
       {car_id:'8'}
   ],

1  _id:5e4d18bd10e5482eb6g57f5rt
   name:'Josh kumar',
   cars_owned:[
       {car_id:'7'},
       {car_id:'9'},
       {car_id:'1'},
       {car_id:'3'}
   ],

2  _id:5e4d18bd10e5482eb6r67222
   name:'Jesse nigam',
   cars_owned:[
       {car_id:'6'},
       {car_id:'7'},
       {car_id:'9'},
       {car_id:'3'}
   ],

3  _id:5e4d18bd10e5482eb6467ii46
   name:'Jordan khan',
   cars_owned:[
       {car_id:'3'},
       {car_id:'1'},
       {car_id:'4'},
       {car_id:'5'}
   ]

现在我想搜索一个用户,其起始名称为“J”,并且我的 cars_owned 输入将是

  'J',cars_owned['3','7','9','12','10']

输出将是

   1  _id:5e4d18bd10e5482eb6g57f5rt
   name:'Josh kumar',
   cars_owned:[
       {car_id:'7'},
       {car_id:'9'},
       {car_id:'1'},
       {car_id:'3'}
   ],

   2  _id:5e4d18bd10e5482eb6r67222
   name:'Jesse nigam',
   cars_owned:[
       {car_id:'6'},
       {car_id:'7'},
       {car_id:'9'},
       {car_id:'3'}
   ],

   0  _id:5e4d18bd10e5482eb623c6e4
   name:'John singh',
   cars_owned:[
       {car_id:'1'},
       {car_id:'5'},
       {car_id:'7'},
       {car_id:'8'}
   ],

   3  _id:5e4d18bd10e5482eb6467ii46
   name:'Jordan khan',
   cars_owned:[
       {car_id:'3'},
       {car_id:'1'},
       {car_id:'4'},
       {car_id:'5'}
   ]

现在您会注意到结果是所有名称以“J”开头的用户,cars_owned 是在 3,7,9,12,10 但降序排列的用户是大多数cars_owned 都在顶部和其他方面相匹配。我希望根据单个 mongo db 查询中匹配的最大 cars_owned 对结果进行排序。到目前为止,我已经做了一个简单的查找查询。

  User_data.find({name: { $regex: "^" + search_name },
                  cars_owned:{$elemMatch:{car_id:'3',car_id:'7',car_id:'9',car_id:'12',car_id:'10'} 
                 }},function(err,resp){

                      console.log(JSON.stringify(resp,null,4));

          });

但它只返回一个文档我想要所有具有任何给定 car_id 但按最大匹配排序的文档。如果您对这个问题有任何不理解,请随时在评论中提问,但请在单个 mongo db 查询中给出答案,我也可以使用 aggeregation 框架。提前致谢。

【问题讨论】:

    标签: node.js mongodb mongoose aggregation-framework


    【解决方案1】:

    您必须为此使用聚合。 首先,您定义列表中有多少用户的汽车是常见的,然后过滤匹配名称和至少一辆汽车常见的结果,最后按常见汽车对结果进行排序。

    这里是查询:

    db.collection.aggregate([
      {
        $addFields: {
          commonCars: {
            $size: {
              $setIntersection: [
                [
                  "3",
                  "7",
                  "9",
                  "12",
                  "10"
                ],
                "$cars_owned.car_id"
              ]
            },
    
          }
        }
      },
      {
        $match: {
          $expr: {
            $and: [
              {
                $eq: [
                  {
                    $regexMatch: {
                      input: "$name",
                      regex: "^J"
                    }
                  },
                  true
                ]
              },
              {
                $gt: [
                  "$commonCars",
                  0
                ]
              }
            ]
          }
        }
      },
      {
        $sort: {
          "commonCars": -1
        }
      }
    ])
    

    And you can test it here


    编辑

    如果您不需要对结果进行排序,您可以在一个匹配阶段实现:

    db.collection.aggregate([
      {
        $match: {
          $expr: {
            $and: [
              {
                $eq: [
                  {
                    $regexMatch: {
                      input: "$name",
                      regex: "^J"
                    }
                  },
                  true
                ]
              },
              {
                $gt: [
                  {
                    $size: {
                      $setIntersection: [
                        [
                          "3",
                          "7",
                          "9",
                          "12",
                          "10"
                        ],
                        "$cars_owned.car_id"
                      ]
                    },
    
                  },
                  0
                ]
              }
            ]
          }
        }
      },
    
    ])
    

    Test it here

    【讨论】:

    • 这是答案,但我想同时搜索名称和普通汽车。在您的回答中,首先扫描所有文档以查找普通汽车,然后在其中获取名称。我也不想搜索名称然后找到我想同时(总共)做的普通汽车。
    • 你可以在 match 阶段执行 $setIntersection 操作,但是在这种情况下你将无法执行 $sort 操作,因为 setIntersection 结果的大小将仅针对 $match 阶段计算.要执行排序,您必须添加...这个 $addFields 阶段。
    • 你能给我一个查询吗?我想得到这个答案。
    • 我已将其添加到我之前的答案中
    • 我的问题已经解决了,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-24
    相关资源
    最近更新 更多