首页 > 解决方案 > 使用数组查询参数 Node/Mongoose 查询数组字段

问题描述

我有一个 Route 架构字段,它是一个字符串数组weekdays: {type:[String], required:false},可以包含 0 到 7 个字符串(使用天数),因此通过查询我还传递了一个数组(工作日范围)以查找工作日数组字段包含的任何记录至少一个查询工作日数组值。

我正在使用weekdays: {$elemMatch: {weekdays},但它不起作用,因为该字段应匹配所有条件,因此所有查询数组。我也尝试了$in操作符,但它使节点崩溃并显示以下消息:

Mongoose Route.findRoutes city weekdays time ranges public error:  CastError: Cast to string failed for value "{ weekdays: '[tue, wed, thu, fri, sat, sun]' }" (type Object) at path "weekdays" for model "Route"
    at model.Query.exec (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:4470:21)
    at model.Query.Query.find (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:2085:8)
    at Function.find (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/model.js:2093:13)
    at exports.findRoutes (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/api/src/controllers/route.controller.js:28:15)
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at Layer.handle [as handle_request] (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express/lib/router/layer.js:95:5)
    at next (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express/lib/router/route.js:137:13)
    at exports.clientApiKeyValidation (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/api/src/auth_utils.js:15:10)
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at Layer.handle [as handle_request] (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express/lib/router/layer.js:95:5) {
  messageFormat: undefined,
  stringValue: `"{ weekdays: '[tue, wed, thu, fri, sat, sun]' }"`,
  kind: 'string',
  value: { weekdays: '[tue, wed, thu, fri, sat, sun]' },
  path: 'weekdays',
  reason: null,
  valueType: 'Object'
}
node:events:346
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property 'length' of undefined
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/api/src/controllers/route.controller.js:54:28
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/model.js:4868:18
    at processTicksAndRejections (node:internal/process/task_queues:76:11)
Emitted 'error' event on Function instance at:
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/model.js:4870:15

在这种情况下使用什么正确的运算符或者如何交叉检查两个数组?一如既往地感谢您的时间和帮助。

这是控制器中的方法:

if (city && region && country && isPublic && weekdays && minTime && maxTime) {
        Route.find(
            {
                city: city,
                region: region,
                country: country,
                
                isPublic: isPublic,
                time: {
                    $gte: minTime,
                    $lte: maxTime
                },
                weekdays: {
                    $elemMatch: {
                        weekdays}
                }

            },
            function (err, result) {
                if (err) {
                    console.log('Mongoose Route.findRoutes city weekdays time ranges public error: ', err);
                    res.status(503).send({
                        error: 'Internal error'
                    });
                }
                if (result.length > 0) {
                    console.log('Mongoose Route.findRoutes city weekdays time ranges public: ', result);
                    res.status(200).send({
                        message: 'Routes found.',
                        data: result
                    });
                } else {
                    console.log('Mongoose Route.findRoutes city weekdays time ranges public : No routes found.');
                    res.status(404).send({ message: 'No routes found' });
                }
            }
        );
    }

这是架构:

const routeSchema = new mongoose.Schema({
    city: { type: String, required: true },
    region: { type: String, required: true },
    country: { type: String, required: true },
    userName: { type: String, required: true },

    routeName: { type: String, required: true },
    routeDistance: { type: String, required: true },
    routeDuration: { type: String, required: true },
    rawTrack: { type: [Object], required: true },
    // snappedToRoad: { type: [Object], required: false },
    tracked: { type: [Object], required: false },
    filtered: { type: [Object], required: false },
    isPublic: {type: Boolean, required: false, default: false},
    weekdays: {type:[String], required:false},
    time : {type:String, required: false}

},
    {
        timestamps: true,
        toObject: { virtuals: true },
        toJSON: { virtuals: true }
    });

标签: node.jsarraysmongoose

解决方案


也许你使用了错误的语法,$in因为在这种情况下它是正确的方法。如果你的weekdays变量是一个数组,你可以使用下面的代码:

Route.find({
  ...
  weekdays: { $in: weekdays },
  ...
})

蒙古游乐场


推荐阅读