Mongoose Arguments 必须是聚合管道操作符
Posted
技术标签:
【中文标题】Mongoose Arguments 必须是聚合管道操作符【英文标题】:Mongoose Arguments must be aggregate pipeline operators 【发布时间】:2017-06-18 00:40:35 【问题描述】:我们正在尝试在 NodeJS 中构建一个函数,该函数允许我们将该函数与查找或聚合参数一起使用并返回结果。
find 选项可以正常工作,limit 和 offset 也可以。但是聚合将不起作用。我们得到错误
参数必须是聚合管道运算符
当我们调用函数时。
模型看起来像(我删除了一些字段)
product.model.js
var Product = new mongoose.Schema(
name: //obsolete
type: String,
required: true
,
nameSlug: //obsolete
type: String,
required: true
,
views:
type: Number,
min: 0,
default: 0,
required: true
,
waterproofLevel:
type: Number,
min: 0,
max: 3000,
default: 0,
required: true
,
productCollection:
type: String
,
male:
type: Boolean,
default: true,
required: true
,
female:
type: Boolean,
default: false,
required: true
,
kids: Boolean,
isBestseller:
type: Boolean,
default: false,
required: true
,
suggestedRetailPrice:
type: Number,
required: true
,
productNumber:
type: String,
required: true
,
ean:
type: String,
minlength: 5,
maxlength: 13,
validate: validators.isNumeric(message: 'Invalid EAN: EAN codes consist of 13 digits'),
required: true
,
brand: [
_id: false,
name:
type: String,
required: true
,
image: [Image]
],
images: [Image],
);
getProducts 函数
module.exports.getProducts = function(req, res)
console.log('[getProducts controller]');
// default values, because offset and limit are required
var filterBy, sortBy, offset, limit, aggregate;
if(req.query)
if(typeof req.query === 'string')
req.query = JSON.parse(req.query);
if(req.query.offset && !isNaN(parseInt(req.query.offset)))
offset = parseInt(req.query.offset);
delete req.query.offset;
if(req.query.limit && !isNaN(parseInt(req.query.limit)))
limit = parseInt(req.query.limit);
delete req.query.limit;
// if any filters are provided in the URL, parse them and add to the filtering or aggregate params object.
if(req.query.aggregate)
aggregate = req.query.aggregate;
else if(req.query.filter)
filterBy = filter(req.query.filter);
// if any sorting parameters are provided in the URL, parse them and add to the Mongoose sorting object.
if(req.query.sort)
sortBy = sort(req.query.sort);
if(req.query.lng && req.query.lat)
// TODO find products close to the given coordinates.
if(aggregate)
console.log("aggregate", aggregate);
var query = Product.aggregate(aggregate).allowDiskUse(true);
else
var query = Product.find(filterBy);
query.skip(offset).limit(limit).exec(function(err, products)
var status, response;
if(err)
status = 500;
response = message: 'Internal server error. ' + err;
else if(!products || products.length == 0)
status = 404;
response = message: 'No products found with the given search criteria. ';
else
status = 200;
response = message: 'OK', products;
console.log(status + ' ' + response.message);
res.status(status).json(response);
);
;
产品系列目前有大约 2500 种产品。因此,我阅读了有关 allowDiskUsage(true)
函数的另一个问题。
我们使用 $api 服务调用该函数,它是 Angular 中 $http 服务的包装器:
var filter =
$match :
'brand.name': brand
console.log("filter", filter);
$api.get('products', 'aggregate': filter, function(response)
console.log(response.data);
, function(response)
console.log("error", response.data);
)
我在函数中登录的时候,聚合参数是正确的,它看起来像:聚合$match:'brand.name':'Microsoft'
有没有人可以告诉我我错过了什么?
【问题讨论】:
【参考方案1】:确保您的操作包含在大括号和方括号内。 mongoDB 将管道运算符作为对象数组。
所以改为这样做:
$lookup: from: "collectionname", localField: "id", foreignField: "u_id", as: "newdoc", ,
这样做
[$lookup: from: "collectionname", localField: "Id", foreignField: "u_id", as: "newdoc", ,]
【讨论】:
【参考方案2】:聚合函数接受一个操作数组-
你需要通过这个
[$match:'brand.name':'Microsoft']
而不是这个
$match:'brand.name':'Microsoft'
或者在猫鼬中,您可以像这样使用流水线 -
Product.aggregate().match('brand.name':'Microsoft').allowDiskUse(true);
【讨论】:
谢谢。你的最后一个建议结合JSON.parse
函数来解析字符串以上是关于Mongoose Arguments 必须是聚合管道操作符的主要内容,如果未能解决你的问题,请参考以下文章
Express + Mongoose + 聚合 + 计算可用库存
在亚马逊 EC2 上托管 nodeJS/mongoose Web 应用程序