我试图在mongoose中构建一种复杂的查询,我的问题是这个查询可以接收的所有参数都是非强制性的,这给我带来了问题。现在我这样做了:
let query = {
publicationType: req.body.searchParams.publicationType
};
if (req.body.searchParams.address) {
query.address = {};
if (req.body.searchParams.address.city) {
query.address.city = req.body.searchParams.address.city;
}
}
try {
const dwellings = await model.Dwelling.find({
$and: [{$or: [{publicationType: req.body.searchParams.publicationType}]},
{
$or: [{
address: [query.address]
}]
}]
}).lean().exec();
console.log(dwellings);
res.send({dwellings});
} catch (err) {
next(err);
}
});
这是试试城市参数是否有效,如果我只按发布类型搜索我得到了想要的结果,如果我添加城市我得到0结果,即使我应该得到更多,我调试mongoose看看查询是如何构建的,它是这样的:
Mongoose: dwelling.find({ '$and': [ { '$or': [ { publicationType: 'Venta' } ] }, { '$or': [ { address: { '$in': [ { city: 'La Plata' } ] } } ] } ] }, { fields: {} })
[]
答案 0 :(得分:1)
在您的代码中,您构建$and expression两个$or expressions ,但每个 $或表达式每个只有一个参数,所以你是有效构建此 $和 find
表达式(请注意,我正在使用下面的mongo
shell语法):
db.dwellings.find({
'$and': [
{ publicationType: 'Venta' },
{ address: { '$in': [ { city: 'La Plata' } ] } }
]
});
...单词:“查找带有publicationType Venta
和 address.city
La Plata
的住所。
如果我添加城市我得到0结果,即使我应该得到更多
因为你提到你希望在添加address.city
时获得更多结果我怀疑你真的希望顶级表达式为$or
而不是$and
,如下所示:
db.dwellings.find({
'$or': [
{ publicationType: 'Venta' },
{ address: { '$in': [ { city: 'La Plata' } ] } }
]
});
您可能希望在mongo
shell中对您的查询进行更多实验,然后再将其表示为代码。如果您的工作站上碰巧有Docker,我发现在容器中运行mongo
是一种在开发过程中对事物进行原型设计的有用方法,例如:
docker run --name mongo -d mongo:3.7
# after mongo is up and running...
docker exec -it mongo mongo
在交互式mongo shell中,您可以插入文档以进行测试并使用find
表达式进行实验,例如:
use stackoverflow;
dwell1 = { publicationType: 'Venta', address: { city: 'Somewhere' } };
dwell2 = { publicationType: 'Something', address: { city: 'La Plata' } };
db.dwellings.insert(dwell1);
db.dwellings.insert(dwell2);
# Try results of $and
db.dwellings.find({ '$and': [
{ publicationType: 'Venta' },
{ address: { '$in': [ { city: 'La Plata' } ] } }
] });
# ... compare to results of $or
db.dwellings.find({ '$or': [
{ publicationType: 'Venta' },
{ address: { '$in': [ { city: 'La Plata' } ] } }
] });
...一旦您插入了一些文档进行测试,请确认您的$and
中是否需要$or
或find
表达。
答案 1 :(得分:0)
所以有了画笔Maclnnis的指导我想出了如何让它至少起作用
const query = {};
if (req.body.searchParams.publicationType !== '') {
query['publicationType'] = req.body.searchParams.publicationType;
}
if (req.body.searchParams.address) {
if (req.body.searchParams.address.streetNumber !== undefined) {
query['address.streetNumber'] = req.body.searchParams.address.streetNumber;
}
if (req.body.searchParams.address.streetName !== undefined) {
query['address.streetName'] = req.body.searchParams.address.streetName;
}
if (req.body.searchParams.address.city !== undefined) {
query['address.city'] = req.body.searchParams.address.city;
}
if (req.body.searchParams.address.state !== undefined) {
query['address.state'] = req.body.searchParams.address.state;
}
if (req.body.searchParams.address.country !== undefined) {
query['address.country'] = req.body.searchParams.address.country;
}
if (req.body.searchParams.address.zip !== undefined) {
query['address.zip'] = req.body.searchParams.address.zip;
}
}
if (req.body.searchParams.price) {
if (req.body.searchParams.price.min !== undefined) {
query['price'] = {$gt: req.body.searchParams.price.min};
}
if (req.body.searchParams.price.max !== undefined) {
query['price'] = {$lt: req.body.searchParams.price.max};
}
}
try {
const dwellings = await model.Dwelling.find({
'$and': [
query
]
}).lean().exec();
console.log(dwellings);
res.send({dwellings});
} catch (err) {
next(err);
}
这可以优化吗?