javascript - 使用 MongoDB 聚合时出现错误, 'Can' t 从 BSON 类型 objectId 转换为 String'

标签 javascript node.js mongodb mongoose

我正在尝试获取用户 1 和用户 N 之间每一次对话的最后一条消息。

我已经成功地将下面的内容编译在一起,但是它抛出了上面提到的错误。我该如何使用 ObjectIds 来解决这个问题,因为这是我在数据库中拥有的,而不是字符串?

    await MostRecentMessages.aggregate(
      [
        {
          $match: {
            $or: [
              { from: mongoose.Types.ObjectId(id) },
              { to: mongoose.Types.ObjectId(id) }
            ],
            deletedBy: { $ne: id }
          }
        },
        { $sort: { date: -1 } },
        { $project: { _id: 1, from: 1, to: 1, conversation: 1, date: 1 } },
        {
          $group: {
            _id: {
              lastMessage: {
                $cond: [
                  {
                    $gt: [
                      { $substr: ["$to", 0, 1] },
                      { $substr: ["$from", 0, 1] }
                    ]
                  },
                  { $concat: ["$to", " and ", "$from"] },
                  { $concat: ["$from", " and ", "$to"] }
                ]
              }
            },
            conversation: { $first: "$$ROOT" }
          }
        },
        {
          $lookup: {
            from: "conversations",
            localField: "conversation",
            foreignField: "_id",
            as: "conversation"
          }
        },
        { $unwind: { path: "$conversation" } },
        {
          $lookup: {
            from: "users",
            localField: "to",
            foreignField: "_id",
            as: "to"
          }
        },
        { $unwind: { path: "$to" } },
        {
          $lookup: {
            from: "users",
            localField: "from",
            foreignField: "_id",
            as: "from"
          }
        },
        { $unwind: { path: "$from" } }
      ],
      function(err, docs) {
        if (err) {
          console.log(err);
        } else {
          console.log("MostRecentMessages", docs);
          return res.json(docs);
        }
      }
    );

我的架构,如果重要的话:

const MostRecentMessageSchema = new Schema({
  to: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user"
  },
  from: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user"
  },
  conversation: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "conversation"
  },
  deletedBy: {
    type: [String]
  },
  date: {
    type: Date,
    default: Date.now
  }
});
<小时/>

编辑

以下是 5 个相关文件:

// db.MostRecentMessages

_id:5dca7a61e95bd3341cad64b9
to:5dca58c21825d8269a32cb10
from:5dca58ce1825d8269a32cb11
conversation:5dca7aea51b626350fa865dd
date:2019-11-12T09:24:49.906+00:00

_id:5dca7ab0d3a44a34c98b7263
to:5dca58ce1825d8269a32cb11
from:5dca58c21825d8269a32cb10
conversation:5dca7ab0d3a44a34c98b7262
date:2019-11-12T09:26:08.125+00:00
// db.Conversation

_id:5dca7a61e95bd3341cad64b8
text:"Test1"
user:5dca58ce1825d8269a32cb11 // sender
recipient:5dca58c21825d8269a32cb10
createdAt:2019-11-12T09:24:49.827+00:00

_id:5dca7ab0d3a44a34c98b7262
text:"Test2"
user:5dca58c21825d8269a32cb10 // sender
recipient:5dca58ce1825d8269a32cb11
createdAt:2019-11-12T09:26:08.105+00:00

_id:5dca7aea51b626350fa865dd
text:"Test3"
user:5dca58ce1825d8269a32cb11 // sender
recipient:5dca58c21825d8269a32cb10
createdAt:2019-11-12T09:27:06.562+00:00

我复制并粘贴了下面的答案,但它只返回带有文本 Test2 的消息

最佳答案

评论中的链接仅供您自己了解... 现在让我们看看什么是有效的(这对你来说可能听起来像“似曾相识”,但它有效!)。所有(以及您前面提到的错误)都发生在$group阶段

db.lastMessage.aggregate([
  {
    $match: {
      $or: [
        {
          from: ObjectId("5a934e000102030405000001")
        },
        {
          to: ObjectId("5a934e000102030405000001")
        }
      ],
      deletedBy: {
        $ne: ObjectId("5a934e000102030405000001")
      }
    }
  },
  {
    $sort: {
      date: -1
    }
  },
  {
    $project: {
      _id: 1,
      from: 1,
      to: 1,
      conversation: 1,
      date: 1
    }
  },
  {
    $group: {
      _id: {
        userConcerned: {
          $cond: {
            if: {
              $eq: [
                "$to",
                ObjectId("5a934e000102030405000001")
              ]
            },
            then: "$to",
            else: "$from"
          }
        },
        interlocutor: {
          $cond: {
            if: {
              $eq: [
                "$to",
                ObjectId("5a934e000102030405000001")
              ]
            },
            then: "$from",
            else: "$to"
          }
        }
      },
      from: {
        $first: "$from"
      },
      to: {
        $first: "$to"
      },
      date: {
        $first: "$date"
      },
      conversation: {
        $first: "$conversation"
      }
    }
  },
  {
    $lookup: {
      from: "conversations",
      localField: "conversation",
      foreignField: "_id",
      as: "conversation"
    }
  },
  {
    $unwind: {
      path: "$conversation"
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "to",
      foreignField: "_id",
      as: "to"
    }
  },
  {
    $unwind: {
      path: "$to"
    }
  },
  {
    $lookup: {
      from: "users",
      localField: "from",
      foreignField: "_id",
      as: "from"
    }
  },
  {
    $unwind: {
      path: "$from"
    }
  }
])

You can verify here 。我刚刚用我在您的其他问题中提供的内容修改了您的小组赛阶段。

关于javascript - 使用 MongoDB 聚合时出现错误, 'Can' t 从 BSON 类型 objectId 转换为 String',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58806223/

相关文章:

javascript - 在异步函数中的 if 语句后使用变量

JavaScript len 函数

node.js - 无法使用 Node.js 中的应用程序洞察 trackEvent() 方法记录冗长的消息

javascript - 如何嵌套查找MongoDB? JavaScript

javascript - 在 OpenShift Gear 上运行 MongoDB 脚本时出错

mongodb - 从Grails从MongoDB 2.4.12迁移到3.2.7的异常

javascript - 无法通过 2 个 html 文件之间的 Angular 服务传递参数

javascript - 如何使用计算属性过滤 VueJS 中 v-for 循环的结果?

node.js - 如何将 postman 中的 include_type_name 设置为 true

node.js - 在 nodejs scrypt 包中使用 Firebase SCrypt 参数