是否可以比较和匹配 MongoDB 中引用文档中的字段

问题描述 投票:0回答:1

我正在尝试使用参考文档在 MongoDB 中实现动态搜索

市场架构:

const MarketSchema = new mongoose.schema({          
    marketName: String,          
    // ... rest of the fields  
}); 

主持人架构:

const ModeratorSchema = new mongoose.Schema({
    name: String,
    username: String,
    // ... rest of the fields
});

现在是我正在尝试处理的文档

主持人到市场映射架构:

const ModeratorToMarketMappingSchema = new mongoose.Schema({
    moderatorId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "User",
    },
    marketId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Market",
    },
    // ... rest of the fields
});

我想根据市场的

marketName
或使用 ModeratorToMarketMapping 文档根据主持人的
name or username
过滤数据。

我希望结果类似于以下查询将产生的结果

如果按市场搜索

SELECT * 
FROM Users AS u
JOIN ModeratorToMarketMapping AS map ON  u.id = map.moderatorId 
JOIN Market AS m ON map.marketId = m.id
WHERE m.marketName LIKE '%${FILTER_VALUE}%'

如果按姓名/用户名搜索

SELECT * 
FROM Users AS u 
JOIN ModeratorToMarketMapping AS map ON  u.id = map.moderatorId 
JOIN Market AS m ON map.marketId = m.id
WHERE u.name LIKE '%${FILTER_VALUE}%' OR u.username LIKE '%${FILTER_VALUE}%'

我想到了两种方法

1]效率较低,但有效

在此解决方案中,如果我想按市场过滤,那么我首先从

Market Collection
搜索“市场”,然后从
id's of moderator
获取
Mapping schema
,然后相应地填充数据,类似地,如果我想按名称或用户名,然后我首先获取
moderators
,然后从
id's of markets
获取
Mapping schema
,然后填充数据

现在很明显,这是一个

not
的好方法,但当要搜索的数据增长时肯定会失败。

2] 看起来高效但部分有效

所以我搜索了第二种方法,最终得到了这个,但这不起作用,因为我希望它起作用。

其代码如下

    const { criteriaKey, filterValue } = req.query;

    let query = {};

    if (criteriaKey && filterValue) {
        const regex = new RegExp(filterValue, "i");

        if (criteriaKey === "market") {
            query = { "market.marketName": { $regex: regex } };
        } else if (criteriaKey === "name") {
            query = {
                $or: [
                    { "moderator.name": { $regex: regex } },
                    { "moderator.username": { $regex: regex } },
                ],
            };
        }
    }

    const moderators = await ModeratorMarketMapping.aggregate([
        {
            $match: query,
        },
        {
            $lookup: {
                from: "markets",
                localField: "marketId",
                foreignField: "_id",
                as: "market",
            },
        },
        {
            $lookup: {
                from: "users",
                localField: "moderatorId",
                foreignField: "_id",
                as: "moderator",
            },
        },
        {
            $unwind: { path: "$market", preserveNullAndEmptyArrays: true },
        },
        {
            $unwind: { path: "$moderator", preserveNullAndEmptyArrays: true },
        },
    ]);

如何使有关代码工作,或者除了切换到 RDBMS 之外还有其他更好的方法吗

node.js database mongodb deployment aggregation-framework
1个回答
0
投票

您设计模式的方式确实需要关系数据,并且您已经通过聚合来解决它。如果您可以使其工作,那么这可能是适合您当前模式的正确方法,但 mongodb 是为灵活性而设计的。在您的情况下,非规范化可能是最佳方法。

您可以像这样存储彼此的引用:

市场架构

const MarketSchema = new mongoose.schema({          
    marketName: String,
    moderatorId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "User",
    },          
    // ... rest of the fields  
});

主持人/用户架构

const UserSchema = new mongoose.Schema({
    name: String,
    username: String,
    marketId: {
        type: mongoose.Schema.Types.ObjectId,
        ref: "Market",
    },
    // ... rest of the fields
});

然后,当您的查询出现时,决定用于查询的模型和

populate
参考,如下所示:

const { criteriaKey, filterValue } = req.query;

if (criteriaKey && filterValue) {
    if (criteriaKey === "market") {
        const docs = await Market.find({ 
            marketName: { 
                $regex: filterValue, $options: 'i' 
            } 
        }).populate('moderatorId');
    } else if (criteriaKey === "name"){
        const docs = await User.find({
            $or: [
                { name: { $regex: filterValue, $options: 'i' } },
                { username: { $regex: filterValue, $options: 'i' } },
            ]
        }).populate('marketId');
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.