【问题标题】:How can I aggregate using a match on two different fields?如何在两个不同字段上使用匹配进行聚合?
【发布时间】:2020-07-23 09:07:38
【问题描述】:

这看起来很简单,但由于某种原因,当我将第二个字段放入 match 语句时,我的聚合返回一个空数组。

我已经检查了这些:

Combining match on text field with aggregate

Match Two different fields in Mongoose, Aggregate?

Mongodb compare two fields with matched fields value aggregate

这就是我想要的:

我想要一个匹配语句来比较我的架构中的两个字段,这些字段仅返回 createdByUserId 的数据并且大于或等于某个开始日期

$match: 
{ $and: 
  [ 
    { createdByUserId: userId }, 
    { dateStart: { $gte: new Date(startDate) } } 
  ] 
}

这就是它的解决方法:

{
  "$match": {
    "$and": [
      {
        "createdByUserId": "5e6c2dddad72870c84f8476b"
      },
      {
        "dateStart": {
          "$gte": "2020-04-10T14:35:02.478Z"
        }
      }
    ]
  }
}

这是我尝试过的

我尝试仅使用 createdByUserId 来简化问题-但是-不起作用

我相信用户 ID 匹配是我的问题的症结

$match: 
{
    createdByUserId: userId
}

确定为:

{
  "$match": {
    "createdByUserId": "5e6c2dddad72870c84f8476b"
  }
}

我认为这可能是一个“字符串到对象 id”的问题并尝试了这个(但它不起作用)

$match: 
{
    createdByUserId: { $eq: {$toOjbectId:userId} }
}

确定为:

{
  "$match": {
    "createdByUserId": {
      "$eq": {
        "$toOjbectId": "5e6c2dddad72870c84f8476b"
      }
    }
  }
}

更多信息

为了展示整个管道,这里是我的聚合:

var match = {
    $match: 
    { $and: 
        [ 
            { createdByUserId: userId }, 
            { dateStart: { $gte: new Date(startDate) } } 
        ] 
    }
};

var lookup ={
    $lookup:
    {
        from: "MyEvents",
        localField: "_id",
        foreignField: "eventId",
        as: "SignedUpUsers"
    }
};

var project = {
    $project: {
        "_id": 1,
        "name": 1,
        "dateStart": 1,
        "createdByUserId": 1
    }
};

var agg = [
    match,
    lookup,
    project
];

Event.aggregate(agg)
.sort({dateStart: 1})
.then( events => {
    if(events){
        return resolve(events);
    }else{
        return reject(null);
    }
})
.catch(err => {
    return reject(err);
})

这是事件架构

const EventSchema = new Schema({
    name: {type: String, required: true},
    dateStart: {type: Date, required: true},
    createdByUserId: {type: Schema.Types.ObjectId, required: true},
})

这是 MyEvents 架构

const MyEventsSchema = new Schema({
    userId: {type: Schema.Types.ObjectId, required: true},
    eventId: {type: Schema.Types.ObjectId, required: true},
})

(集合中有需要返回的数据)

如何匹配两个不同的字段?

更新

感谢 whoami,这可行:

const mongoose = require("mongoose");

 {
   $match: {
     createdByUserId: mongoose.Types.ObjectId(userId);
   }
 }

但是谁能告诉我为什么这不会将字符串更改为对象 id:

{$toOjbectId:userId}

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    您可以遵循此准则

    $match: {
        $and: [
          {
            "createdByUserId": "5e6c2dddad72870c84f8476b"
          },
          {
            "dateStart": {
              $gte: "2020-04-10T14:35:02.478Z"
            }
          }
        ]
      }
    

    【讨论】:

      【解决方案2】:

      是的,问题应该是输入的类型是string Vs DB 字段的类型是ObjectId()。三种方法可以做到:

      一种方式:聚合查询的变化

       {
          $match: {
            $expr: {
              $eq: [
                userId,
                {
                  $toString: "$createdByUserId" // Convert existing 'ObjectId()' to String
                }
              ]
            }
          }
        }
      

      测试: MongoDB-Playground

      第二种方式:在猫鼬中将string转换为ObjectId()

      const mongoose = require("mongoose");
      
          {
            $match: {
              createdByUserId: mongoose.Types.ObjectId(userId);
            }
          }
      

      第三种方式:

      db.collection.aggregate([
        {
          $match: {
            $expr: {
              $eq: [
                {
                  $toObjectId: "5e6c2dddad72870c84f8476b" /** Convert input to ObjectId() using aggregation */
                },
                "$createdByUserId"
              ]
            }
          }
        }
      ])
      

      测试: MongoDB-Playground

      您的查询有问题:因为$ObjectId 是一个聚合运算符 - 您需要在$match 中使用聚合语法。

      我更喜欢第二个过程,因为它可能具有更好的性能并在createdByUserId 字段上使用索引。无论如何,您始终可以使用explain 来测试您的查询性能。

      【讨论】:

      猜你喜欢
      • 2018-07-11
      • 2020-12-10
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2021-04-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多