【问题标题】:Mongoose elemMatch returns an empty arrayMongoose elemMatch 返回一个空数组
【发布时间】:2019-05-21 22:02:27
【问题描述】:

我目前正在构建一个 Web 应用程序,但偶然发现了一个在过去 12 小时内无法解决的问题。

我正在研究一种基本的 get 方法,我试图检索员工正在工作的某些工作职位(即收银员、文员)(客户端工作得很好)。

WorkPosition 的猫鼬模型是这样的(models/work-position.js):

var mongoose = require('mongoose');
var User = require('./user');
var Schema = mongoose.Schema;
var schema = new Schema ({
    workplace : {type: String, required: true},
    type : {type: String, required: true},
    status : {type: String, required: true},
    color : {type: String, required: true},
    employees: [{type: Schema.Types.ObjectId, ref:'User'}]
 });

module.exports = mongoose.model('WorkPosition', schema);

我的get方法(routes/work-position.js):

var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
var User = require('../models/user');
var mongoose = require('mongoose');

var WorkPosition = require('../models/work-position');

router.get('/:userId', function(req, res, next) {
    const userId = req.params.userId;
    WorkPosition.find({employees: {$elemMatch : {$eq: userId}}})
        .exec(function(err, workPositions) {
            if(err) {
                return res.status(500).json({
                    title: 'an error has occurred',
                    error: err
                });
            }
            console.log(userId);
            console.log(workPositions);
            res.status(200).json({
                message: 'Success',
                obj: workPositions
            });
        });
});

当我尝试使用 $elemMatch 方法时出现问题。上面的代码,当 WorkPosition.find 行改为

WorkPosition.find()

没有任何条件(

{employees: {$elemMatch : {$eq: userId}}}

) 在里面,我成功地检索到了我想要的 WorkPosition 文档。

但是,我只想检索 WorkPosition 中的“employees”字段与我从 req.params 收到的“userId”匹配的 WorkPosition 文档。因此,我搜索了mongodb/mongoose API (http://mongoosejs.com/docs/api.html#query_Query-elemMatch)

我在哪里找到了 $elemMatch 方法。

在 mongodb shell 中,当我这样做时

db.workpositions.find({"employees": { $elemMatch : {$eq: "596823efbac11d1978ba2ee9"}}})

其中“5968....”是userId,我可以成功查询WorkPosition文档。

通过这个命令,我可以验证我的逻辑是否正确,并且使用 mongodb native shell 命令可以得到我想要的文档。

但是,当我尝试将相同的逻辑转换为 Mongoose API 时:

WorkPosition.find().elemMatch('employees', {$eq : userId})

我得到一个空数组,并添加行

mongoose.set('debug', function (coll, method, query, doc) {
    console.log(coll + " " + method + " " + JSON.stringify(query) + " " + JSON.stringify(doc));
});

在 /app.js 中,我可以看到 mongoose 查询转换为本地 mongodb 命令的内容:

workpositions find {"employees":{"$elemMatch":{"$eq":"596823efbac11d1978ba2ee9"}}} {"fields":{}}

。集合(工作位置)、方法(查找)、要查找的数组(员工)和所有内容都正确转换为本地 mongodb 命令,除了

"$eq"

。成功运行的 shell 命令和我代码中的 mongoose 命令之间的唯一区别是 '$eq' 周围的附加引号。

外壳:

db.workpositions.find({"employees": { $elemMatch : {$eq: "596823efbac11d1978ba2ee9"}}})

猫鼬:

db.workpositions.find({"employees": { $elemMatch : {"$eq": "596823efbac11d1978ba2ee9"}}})

我似乎找不到摆脱这些多余引号的方法(我认为这是问题的原因)。我尝试将本机命令与猫鼬一起使用:

mongoose.connection.db.workpositions.find(.....)

但这也会导致错误。

通过猫鼬使用 elemMatch 的正确方法是什么?谁能告诉我如何使用它?我尝试了所有我能想到的方法,但我似乎无法解决这个问题。

我正在考虑更改 WorkPosition.employees 字段,以便它包含实际用户(不仅是 userId),并且我可以使用与 Mongoose elemMatch API 完全匹配的其他信息进行解析。但是,我相信这会浪费大量的数据库空间,因为每个 WorkPosition 都必须携带一组用户。

要在用户和 WorkPositions 之间建立正确的关系,elemMatch 是我的项目中的一项要求。我将非常感谢任何帮助!

【问题讨论】:

  • 由于您的员工字段只是一个 id 数组,您可以不只使用:WorkPosition.find({ employees: userId })
  • 引用您的问题“在 mongodb shell 中,当我执行 db.workpositions.find({"employees": { $elemMatch : {$eq: "596823efbac11d1978ba2ee9"}}}) 时,我成功了(原文如此)”。所以有你的问题。如果您可以在“shell”中运行该查询,那么 "employees" 的内容实际上是“字符串”和 not ObjectId 值,这是您的架构所期望的。似乎您现有的数据有问题,您需要将这些条目修复为 ObjectId 值。 shell 查询应该失败,因为您没有转换值。 Mongoose 正在尝试转换值。
  • 为了将来参考,请始终将mongoose.set('debug',true) 添加到您的程序中。这会记录从您的 mongoose 模型发出的所有查询,然后您应该能够看到像刚才说明的那样明显的差异。
  • 首先,感谢@NeilLunn 指出我犯的小但重大的错误。我的文档和架构之间存在不一致(字符串不是 ObjectId!)。 elemMatch 成功返回我想要的!
  • @SteveHolgado 我担心如果字段是数组, find({employees: userId}) 将无法工作,但我已经尝试过了,并且也成功地工作了。谢谢你们!

标签: node.js mongodb mongoose


【解决方案1】:

在比较mongodb ObjectIds时,请在$eq数组运算符周围使用mongoose.Types.ObjectId,然后您可以使用$elemMatch运算符检索第一个符合条件的文档。

$elemMatch:{$eq:mongoose.Types.ObjectId(userId)}

【讨论】:

    猜你喜欢
    • 2019-04-27
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2012-12-20
    相关资源
    最近更新 更多