I am trying implement Dynamic Searching in MongoDB with Referenced Documents

市场方案:

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的市场或基于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中搜索‘Markets’,然后从Mapping schema中获取id's of moderator,然后相应地填充数据,类似地,如果我想要按名称或用户名搜索,那么我首先获取moderators,然后从Mapping schema中获取id's of markets,然后填充数据

现在很明显,这是一个很好的方法,当要搜索的数据增长时,它肯定会失败.

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 },
        },
    ]);

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

推荐答案

您设计模式的方式确实需要关系数据,并且您已经使用聚合来处理它.这可能是适合您当前模式的方法,如果您可以让它工作的话,但是MongoDB是为灵活性而设计的.在你的情况下,go 正规化可能是一个最佳的方法.

您可以存储彼此的引用,如下所示:

Market Schema:

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

Moderator/User Schema:

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');
    }
}

Node.js相关问答推荐

需要关于基于角色授权的设计建议

如何将信号从终端窗口发送到运行在Raspberry Pi上的Puppeteer/Node.js上的webscraper

使用HTTPS从NodeJS 17.9.1升级到18.0.0后,SignalR连接失败

是否可以在 NodeJS 代码库中的每个函数之前和之后添加 console.log?

DynamoDB 分页数据检索

仅在 vue 脚本未退出的情况下使用 docker 时出现错误

如何在套接字对象中存储或添加数据?

Docker node_modules 文件夹上的 React 应用程序不可用

如何使用 $PATH 变量在系统中全局自动安装 bash 脚本?或者重写脚本到node

在 nodejs 中使用 multer 上传文件返回未定义的 req.file 和空的 req.body

(Mongoose) 删除 TTL 字段失败

如何使用 Jest 模拟异步函数的延迟时间

简单的 Node js 程序但执行顺序似乎不同?

通过 npm 导入 Sass

如何使用 Mocha 测试正常(非 node 特定)JavaScript 函数?

AngularJS +sails.js

通过 POST 请求将数据从 node.js 服务器发送到 node.js 服务器

Node.js 17.0.1 Gatsby 错误-数字信封 routine ::不支持 ... ERR_OSSL_EVP_UNSUPPORTED

如何忽略文件 grunt uglify

deno vs ts-node:有什么区别