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 应用程序

Mongoose 聚合并获得点赞数

Mongoose 虚拟填充和聚合

在 Mongo 聚合中使用 Cursor() 和 Mongoose

Mongoose 按标签聚合分组项目