Node.js Mongo DB如何在两个数组中查找公共项,并在单个查询中按降序排序

Node.js Mongo DB如何在两个数组中查找公共项,并在单个查询中按降序排序,node.js,mongodb,mongoose,aggregation-framework,Node.js,Mongodb,Mongoose,Aggregation Framework,这是我保存在数据库中的数据 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:[

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

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”的用户,同时搜索我拥有的汽车,输入将是

  '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']
   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”开头,拥有的汽车在3,7,9,12,10中,但按降序排列,这就是拥有最多汽车的用户在顶部匹配,并与其他用户匹配。我希望在单个mongo db查询中根据匹配的最大汽车数对结果进行排序。到目前为止,我已经做了一个简单的find查询

  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查询中给出答案。我也可以使用聚合框架。提前感谢。

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

问题是:

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
    }
  }
])


编辑

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

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
            ]
          }
        ]
      }
    }
  },

])

答案就是这样,但我想同时搜索姓名和普通汽车。在您的回答中,首先扫描所有文档以查找普通汽车,然后在其中获取名称。我也不想搜索名称,然后查找常见的车辆,我想同时(总共)搜索这两种车辆。您可以在匹配阶段执行$setcrossion操作,但在这种情况下,您将无法执行$sort操作,因为setcrossion结果的大小将仅为$match阶段计算。要执行排序,您必须添加。。。这个$addFields阶段。你能给我一个问题吗?我想得到这个答案。我把它添加到我以前的答案中。我的问题解决了,我已经接受了答案。谢谢。