填充字段并查找 - Mongoose

3
我有一个包含支票信息的集合和一个包含每个支票对应的的集合。
我的目标是在支票上编写一些查询,但我需要在填充付款人信息后执行搜索(以获取名称)。
const search = req.query.search || "";
const cheques = await Cheque
    .find({
        isCancelled: false,
        dueDate: { $gte: sinceDate, $lte: tillDate }
    })
    .select("_id serial dueDate value payee")
    .skip(page * limit)
    .limit(limit)
    .sort({ dueDate: -1, serial: 1 })
    .populate({
        path: "payee",
        select: "name"
    })

我想要做的是将这段代码放在我的代码中的某个位置。

match: {
    name: { $regex: search, $options: "i" }
   },

我尝试将匹配放在populate中,但是这样它仍然会找到所有支票,即使它们不满足population匹配但作为null填充。

2个回答

1
我不喜欢这个答案,希望有人能发布更好的答案,但我在网上搜索了很久都没有找到。 我唯一能找到的方法是在聚合中使用$lookup方法。
因此,您需要将代码从调用.find()更改为.aggregate()
这并不是令人沮丧的消息,反而很好,稳定而且没有任何问题。但我讨厌它,因为它可能会改变您在代码中遵循的某些模式。
const search = req.query.search || "";
    const cheques = await Cheque
        .aggregate([
             {
               $lookup: { // similar to .populate() in mongoose
                from: 'payees', // the other collection name
                localField: 'payee', // the field referencing the other collection in the curent collection
                foreignField: '_id', // the name of the column where the cell in the current collection can be found in the other collection
                as: 'payee' // the field you want to place the db response in. this will overwrite payee id with the actual document in the response (it only writes to the response, not on the database, no worries)
             },
             { // this is where you'll place your filter object you used to place inside .find()
               $match: {
                 isCancelled: false,
                 dueDate: { $gte: sinceDate, $lte: tillDate }
                 'payee.branch': 'YOUR_FILTER', // this is how you access the actual object from the other collection after population, using the dot notation but inside a string.
               }
             },
             { // this is similar to .select()
               $project: {_id: 1, serial: 1, dueDate: 1, value: 1, payee: 1}
             },
             {
               $unwind: '$payee' // this picks the only object in the field payee: [ { payeeDoc } ] --> { payeeDoc }
             }
        ])
        .skip(page * limit)
        .limit(limit)
        .sort({ dueDate: -1, serial: 1 })

请注意,您不能再像在.find()上那样在模型查询中链接.select().populate(),因为现在您正在使用返回不同类实例的.aggregate()
  • 如果您想要的话,可以调用.projcet()而不是在聚合数组中执行,但据我所知,您不能使用.select()方法。

我基于个人意见的解决方案是,在支票集合中包含您需要用于筛选的收款人信息。

在我的情况下,这是因为我正在为用户角色和权限而进行过滤,以便某人无法看到另一个人正在查看的内容。

这取决于您,但这将使您稍后生成报告更加容易(我假设您正在开发一项付款服务)。


1
这是非常有帮助的答案,虽然改变代码模式有点令人沮丧,但至少现在我将拥有可工作的代码。感谢你们的评论,它们真的很有帮助!(顺便说一下,这不是支付服务,我只是将我的车间 MS Access 数据库转换为基于 Web 的 Mongo 数据库) - Assad Anabosi

0

populate() 是由 mongoose 提供的一个功能,它首先根据给定条件获取所有的 Cheques,然后再使用 _id 查询 payee 来填充你想要的字段。 https://mongoosejs.com/docs/api.html#query_Query-populate

通过在 populate 中添加 match,你可以过滤需要填充的支票,但不是支票本身。

一个简单的解决方案是过滤已经填充为 null 的支票,并将其返回以供使用。

如果你看到更多这样的查询和/或集合非常庞大,最好将收款人姓名添加到 Cheques 集合中,如果这符合你的目的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接