将 mongo 查询转换为聚合查询?

Convert mongo query to aggregate query?

我是 MongoDB 的新手。我有一个用例,其中 mongo query 应该转换为 aggregate query.

我有以下两个合集:

items: {_id: "something", "name": "raj", "branch": "IT", subItems: ["subItemId","subItemId"]}

subItems: {_id: "something", "city": "hyd", list: ["adsf","adsf"]}

用户传递的查询是:

{
    "query": { "name": "raj", "subItems.loc": "hyd" },
    "sort": { "name": 1 },
    "projection": { "_id": 0, "branch": 1, "subItems.loc": 1 }
}

我可以通过以下方式创建动态查询:

        let itemConditions: any[] = [];
        let subItemConditions: any[] = [];
        let itemProjection: {[k:string]: any} = {};
        let subItemProjection: {[k:string]: any} = {};
        subItemConditions.push({$in: ["$_id", "$$subItems"]}); // Default condition to search files in the subItems collection
        let isAnysubItemProj = false;
        Object.keys(reqQuery).forEach(prop => {
            let value = reqQuery[prop];
            if(prop.includes('subItems.')) {
                key = prop.split(".")[1];
                if(key === '_id') value = new ObjectId(value);
                subItemConditions.push({$eq: [`$${prop}`, value]});
                return;
            }                
            itemConditions.push({$eq: [`$${prop}`, value]});
        });
        if(config.projection)
            Object.keys(config.projection).forEach(prop => {
                if(prop.includes('subItems.')) {
                    isAnysubItemProj = true;
                    const key = prop.split(".")[1];
                    subItemProjection[key] = config.projection[prop];
                    return;
                }
                itemProjection[prop] = config.projection[prop];
            });
        if(isAnysubItemProj) itemProjection['subItems'] = 1;
        let subItemPipeline: any[] = [];
        subItemPipeline.push(
            { $match: {
                $expr: {
                    $and: subItemConditions
                }
            }
        });
        if(Object.keys(subItemProjection).length)
            subItemPipeline.push({$project: subItemProjection});
        let query: any[] = [
            { 
                $match: {
                    $expr : {
                        $and: itemConditions
                    }
                }
            },
            {
                $addFields: {
                    subItems: {
                        $map: {
                            input: "$subItems",
                            as: "id",
                            in: { $toObjectId: "$$id" }
                        }
                    }
                }
            },
            {
                $lookup: {
                    from: "subItems",
                    let: {subItems: "$subItems"},
                    pipeline: subItemPipeline,
                    as: "subItems"
                }
            }
        ];
        if(config.sort && Object.keys(config.sort).length) query.push({$sort: config.sort});
        if(Object.keys(itemProjection).length) query.push({$project: itemProjection});
        const items = await collection.aggregate(query).toArray();

以上代码仅适用于分别比较项目和子项目的相等性,但用户可以发送不同类型的查询,如:

{
  "query": { $or: [{"name": "raj"}, {subItems: {$gt: { $size: 3}}}], "subItems.city": "hyd" },     
  "sort": { "name": 1 },     
  "projection": { "_id": 0, "branch": 1, "subItems.loc": 1 } 
}

{
  "query": { $or: [{"name": "raj"}, {"subItems.city": {"$in" : ["hyd", "ncr"]}}], "subItems.list": {"$size": 2} },     
  "sort": { "name": 1 },     
  "projection": { "_id": 0, "branch": 1, "subItems.loc": 1 } 
}

是否有任何简单的方法可以将此正常 MongoDB 查询转换为聚合查询,或者是否有任何其他方法来实现此...??

我正在尝试修改上述动态查询以处理用户传递的任何查询,但处理所有查询变得越来越困难。

有没有更好的方法来处理这种情况,比如更改用户传递的查询或在服务器端处理它的方式,或者我应该如何更改我的代码以支持用户传递的所有类型的查询..??

任何帮助将不胜感激

如果这确实是您的意见

input = {
    "query": { "name": "raj", "subItems.loc": "hyd" },
    "sort": { "name": 1 },
    "projection": { "_id": 0, "branch": 1, "subItems.loc": 1 }
}

那么聚合管道就是:

let pipeline = [
   {$match: input.query},
   {$sort: input.sort},
   {$project: input.projection}
]

db.collection.aggregate(pipeline)