Mongoose - 按填充对象的字段搜索对象

时间:2018-05-02 16:08:04

标签: javascript node.js mongodb mongoose

我有一个猫鼬模式:

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

它给出一个null。这是一个样本租赁对象,在popluating:

之后
{"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}

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

3 个答案:

答案 0 :(得分:1)

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

  1. 通过“卡号”
  2. 查询用户来获取用户ID
  3. 获取分配了上述用户ID的租借
  4. 这可能如下所示:

    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()返回多个租借。

答案 1 :(得分:0)

您的问题似乎是您尝试通过字段userId.idNumber搜索来查询单个文档。如果这是您想要的所有内容,则只需使用findOne()和您想要匹配的特定字段即可进行简单搜索。

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

答案 2 :(得分:0)

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

我认为您可以尝试这样的事情。

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

以下是我发现的另一则帖子的一些评论,这些评论过去曾为我解答过此问题。仅供参考,这是由sbrass发布的。为此,应归功于他们。这是链接:link to original post

$ lookup就像.populate()一样,用实际数据替换引用。尽管它可以用来匹配多个文档,但是它返回一个数组。

$ unwind从数组中删除项目,在这种情况下,将把单个元素数组变成一个字段。

然后

$ match听起来像什么,只返回与查询匹配的文档。如果需要,您还可以执行比严格相等更复杂的匹配。

通常,聚合管道的工作方式是不断过滤/修改匹配文档的每一步,直到您拥有所需的内容为止。

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