Mongoose:如果查询中的参数为空,则忽略该参数
Posted
技术标签:
【中文标题】Mongoose:如果查询中的参数为空,则忽略该参数【英文标题】:Mongoose: ignore parameter in query if it is null 【发布时间】:2018-09-01 09:03:28 【问题描述】:我有一个简单的 REST API,我想在特定端点上实现过滤。
想象一下我有一个这样的端点:
localhost:5000/api/items?color="red"
处理这样的请求:
const items = await Items.find(color: req.query.color)
当存在color
参数时,此方法有效。但是,如果省略 color
参数,则查询将搜索 color
为 undefined
的项目。这不是我需要的行为。
在我的情况下,我想添加 多个过滤器参数,如果它们不存在,它们将被忽略。我是否必须为每个案例创建单独的查询,或者是否可以选择告诉 Mongoose 不要搜索字段(在本例中为 color
)如果它是 null 或未定义?
【问题讨论】:
【参考方案1】:您可以使用“destructuring assignment”解压缩 req.query 中的变量。
const color = req.query;
if(color)
const items = await Items.find( color )
如果您有多个过滤器,则可以使用上面的变量。例如,您可能有color
和type
参数。这样,您可以构建一个对象以传递给 find 方法。
const color, type = req.query;
let query = ;
if(color)
query.color = color;
if(type)
query.type = type;
const items = await Items.find(query);
如果color
或type
不在原始查询中,它们将是未定义 或falsy,因此将跳过该参数的if 语句。
希望它有效!
【讨论】:
这是我希望避免的,因为如果我有 5 个以上的参数,我需要对每种可能性进行查询,即 32。 我刚刚进行了更新。您认为以下解决方案对您有用吗?【参考方案2】:我刚刚遇到了同样的问题,如果你使用的是支持 ES6 的节点版本,你应该可以使用 spread。它会自动处理未定义的
var filters =
colour: "red",
size: undefined
Items.find(...filters)
// only colour is defined, so it becomes
Items.find(colour:"red")
如果你使用 Babel,请注意。您可能需要先定义一个对象。
var query = ...filters
Items.find(query)
【讨论】:
【参考方案3】:您可以在传递该对象之前从该对象中删除未定义的键。
Object.keys(filter).forEach(key => filter[key] === undefined && delete filter[key])
把上面的代码放在 util 里面,到处重复使用。
【讨论】:
【参考方案4】:您可以在连接到 MongoDB 时在连接选项中使用ignoreUndefined
,这样当您的查询中所有未定义的键被序列化为 BJSON 时,它们都会被跳过。你可以在这个page上看到选项
【讨论】:
【参考方案5】:正如 francisct 所说,您可以通过在连接选项中使用 ignoreUndefined
来实现此目的而无需执行任何手动检查:
const mongoose = require('mongoose');
mongoose.connect(mongoDb, ignoreUndefined: true );
或者,您可以使用reduce
将您在查询中查找的选项显式指定为数组,并仅使用不是undefined
的字段构造过滤器对象:
const query = color: 'red', price: 2, hello: 'world' ;
const fields = ['color', 'price', 'size'];
function getFilter(query, fields)
return fields.reduce((filter, field) =>
if (query[field] !== undefined)
return
[field]: query[field],
...filter,
;
return filter;
, );
const filter = getFilter(query, fields); // price: 2, color: 'red'
在这种情况下,函数不会将“hello”字段添加到对象中,因为“hello”不在数组中。它也忽略“大小”,因为它不在查询中。您可以像这样使用返回的对象:
const items = await Items.find(filter);
您可以使用隐式返回和三元运算符来缩短此函数:
const getFilter = (query, fields) => fields.reduce(
(filter, field) => query[field] !== undefined ?
[field]: query[field],
...filter,
: filter,
);
很酷,尽管可读性差。
【讨论】:
【参考方案6】:我也有这个问题。这是我的解决方案:
在连接设置中添加ignoreUndefined
我正在使用nestjs
MongooseModule.forRootAsync(
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => (
uri: configService.get<string>('MONGO_URI'),
useCreateIndex: true,
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true,
ignoreUndefined: true, // add this to the option
connectionFactory: (connection) =>
connection.plugin(require('mongoose-autopopulate'));
return connection;
,
)
这是查询日志:
Mongoose: entry.find( field: undefined )
然后我得到了所有的条目
【讨论】:
以上是关于Mongoose:如果查询中的参数为空,则忽略该参数的主要内容,如果未能解决你的问题,请参考以下文章
mongodb/mongoose:如果来自nestjs的数据不为空,则保存唯一值