【问题标题】:Mongoose - searching for object by field of populated objectMongoose - 按填充对象的字段搜索对象
【发布时间】:2023-04-01 21:45:01
【问题描述】:

我有一个猫鼬模式:

var ClientRentalSchema = new mongoose.Schema({
    carId: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Car'
    },
    userId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User'
    },
    startDate: Date,
    endDate: Date,
    payment: Number,
    status: { type: String, default: "Oczekujące" },
    discount: { type: Number, default: 0 }
});

现在,我正在尝试通过用户的身份证号码来查找对象。首先,我得到的最接近的是这段代码:

Rental.find()
         .populate('userId', 'idNumber')
         .findOne({'userId.idNumber': 'XYZ 987654'})
        .exec( (err, values) => {
            if(err) return err;
            res.json(values);
    })

它给出一个空值。这是填充后的示例租赁对象:

{"status":"Aktywne",
"discount":0.2,
"_id":"5ae06b49abafb90e20359892",
"carId":"5ad6186ebd371940e4131f71",
"userId":{"_id":"5ad8e077a59b7d58fc2384bd",
    "idNumber":"ABC 123456"},
"startDate":"2018-04-26T09:11:00.000Z",
"endDate":"2018-04-29T09:11:00.000Z",
"payment":237.6,
"__v":0}

通过用户身份证号码搜索租赁的正确方法是什么?

【问题讨论】:

  • 这似乎与以下内容重复:stackoverflow.com/questions/31357745/…,看起来答案是在填充上运行.exec(),然后在 javascript 中过滤或更改架构以包含基本架构中的整个用户对象. (这些答案都不是很好,但根据您的情况可能会起作用)

标签: javascript node.js mongodb mongoose


【解决方案1】:

不幸的是,mongoose 似乎使这种情况有点棘手,因为它不支持 JOINS。我认为我们需要的是两个查询:

  1. 通过查询用户的“卡号”来获取用户 ID
  2. 获取分配了上述用户 ID 的租赁

这可能看起来像:

Users.findOne({'userId': 'XYZ 987654'}), (err, user) => {
    if(err) return err;

    if(user) {
      Rental
        .findOne({'userId': user._id}), (err, rental) => {
          if(err) return err;
          res.json(rental);
      });
    }
  });

这可以很容易地切换为接受多个用户“卡号”并使用find()而不是findOne()返回多个租金。

【讨论】:

  • 不得不进行一些编辑,修复了租赁查询以将 userId 与之前返回的 user._id 进行比较。此外,通过删除exec() 并将函数作为参数传递给findOne() 来缩短语法。我还发现这篇文章可能会提供更多帮助:stackoverflow.com/questions/19380738/…
  • 但是没有必要放置两个查询,因为它可以使用单个查询轻松完成
【解决方案2】:

您的问题似乎是您试图通过字段 userId.idNumber 搜索来查询单个文档。如果这就是您想要做的所有事情,那么您需要使用 findOne() 与您想要匹配的特定字段进行简单搜索。

Rental.findOne({'userId.idNumber': 'XYZ 987654'}, function(err, rentalDoc) {
        if(err) return err;
        res.json(values);
})

【讨论】:

    【解决方案3】:

    在这里聚会有点晚了。您可以使用的一件事是 Mongodb 聚合管道。

    我觉得你可以试试这样的。

    Rental.aggregate([
      {
        $lookup: {
          from: 'users',
          localField: 'userId',
          foreignField: '_id',
          as: 'rentalUsers'
        }
      },
      {$match: {'rentalUsers.idNumber': 'XYZ 987654'} }
    ])

    以下是我发现的另一篇文章中的一些 cmets,它们过去曾为我回答过这个问题。仅供参考,这是由sbrass 发布的。这要归功于他们。这是链接:link to original post

    $lookup 的作用类似于 .populate(),将引用替换为实际数据。它返回一个数组,因为它可以用于匹配多个文档。

    $unwind 从数组中删除项目,在这种情况下只会将单个元素数组转换为字段。

    $match 然后做它听起来的样子,只返回与查询匹配的文档。如果需要,您还可以进行比严格相等更复杂的匹配。

    一般来说,聚合管道的工作方式是在每个步骤中不断过滤/修改匹配的文档,直到你得到你想要的。

    免责声明:我没有测试过这个 sn-p,所以我不能说这个查询确实有效。我最近写了一个类似的查询,这就是我解决问题的方法。您可能需要进行一些调整以满足您的需求。希望这可以帮助。干杯!

    【讨论】:

      猜你喜欢
      • 2023-01-05
      • 1970-01-01
      • 2019-06-23
      • 2015-11-10
      • 2021-07-09
      • 1970-01-01
      • 1970-01-01
      • 2018-08-11
      • 2017-10-03
      相关资源
      最近更新 更多