首页 > 解决方案 > 使用猫鼬填充过滤数据

问题描述

我有两个数据结构“数据库”和“组件”

const DatabaseSchema = mongoose.Schema({
    components: [{ type: Schema.Types.ObjectId, ref: 'Components', required: false }],
});
const ComponentsSchema = mongoose.Schema({
    name: { type: String, required: true, trim: true, unique: true, lowercase: true },
    updatedAt: Date,
});

我想按组件名称过滤数据库中的所有项目

我正在使用的搜索规则

Database.find({
    components: { $elemMatch:  { name: /antr/i } }
}).populate({
    path: 'components',
    select: 'name -_id'
}).select(['descript','components']).exec( (err,data) => {
    console.log(err);
    res.json(data);
});

但是总是返回一个空元素

标签: javascriptnode.jsmongodbmongooserelationship

解决方案


请试试这个:

正如我已经建议你可以使用这个:

Database.find({})
    .populate({ path: 'components', match: { name: /antr/i }, select: 'name -_id' })
    .exec((err, data) => { console.log(err); res.json(data); });

由于您看到空数组是因为过滤器查询在match数据库文档的组件数组中的组件集合 wrt ObjectIds 中找不到合适的文档,这是正常的。也许你可以在代码中过滤掉那些,因为你不是这样看的,你可以使用 mongoDB 的$lookup来自聚合框架,它相当于.populate()来自 mongoose。

Database.aggregate(
    [{
        $lookup: {
            from: "components",
            "let": { "ids": "$components" },
            pipeline: [
                { $match: { $expr: { $in: ['$_id', '$$ids'] } } }],
            as: "dbComponentsArray"
        }
    }, { $unwind: '$dbComponentsArray' }, { $match: { 'dbComponentsArray.name': /antr/i } },
    { $group: { _id: '$_id', dbComponentsArray: { $push: '$dbComponentsArray' }, data: { $first: '$$ROOT' } } }, { $addFields: { 'data.dbComponentsArray': '$dbComponentsArray' } },
    { $replaceRoot: { 'newRoot': '$data' } }])

集合中的示例数据:

成分 :

/* 1 */
{
    "_id" : ObjectId("5d481cd098ba991c0857959f"),
    "name" : "antracito",
    "updatedAt" : ISODate("2019-08-05T12:10:56.777Z"),
    "__v" : 0
}

/* 2 */
{
    "_id" : ObjectId("5d481cd098ba991c0857958f"),
    "name" : "anacito",
    "updatedAt" : ISODate("2019-08-05T12:10:56.777Z"),
    "__v" : 0
}

/* 3 */
{
    "_id" : ObjectId("5d481cd098ba991c0857951f"),
    "name" : "antracito",
    "updatedAt" : ISODate("2019-08-05T12:10:56.777Z"),
    "__v" : 0
}

/* 4 */
{
    "_id" : ObjectId("5d481cd098ba991c0857952f"),
    "name" : "anacito",
    "updatedAt" : ISODate("2019-08-05T12:10:56.777Z"),
    "__v" : 0
}

数据库:

/* 1 */
{
    "_id" : ObjectId("5d4979d52a17d10a6c8de81b"),
    "components" : [ 
        ObjectId("5d481cd098ba991c0857951f"), 
        ObjectId("5d481cd098ba991c0857952f"), 
        ObjectId("5d481cd098ba991c0857953f"), 
        ObjectId("5d481cd098ba991c0857959f")
    ]
}

输出 :

/* 1 */
{
    "_id" : ObjectId("5d4979d52a17d10a6c8de81b"),
    "components" : [ 
        ObjectId("5d481cd098ba991c0857951f"), 
        ObjectId("5d481cd098ba991c0857952f"), 
        ObjectId("5d481cd098ba991c0857953f"), 
        ObjectId("5d481cd098ba991c0857959f")
    ],
    "dbComponentsArray" : [ 
        {
            "_id" : ObjectId("5d481cd098ba991c0857959f"),
            "name" : "antracito",
            "updatedAt" : ISODate("2019-08-05T12:10:56.777Z"),
            "__v" : 0
        }, 
        {
            "_id" : ObjectId("5d481cd098ba991c0857951f"),
            "name" : "antracito",
            "updatedAt" : ISODate("2019-08-05T12:10:56.777Z"),
            "__v" : 0
        }
    ]
}

推荐阅读