Javascript 如何在MongoDB中按引用字段查询?
我有两个Mongo模式: 用户: 国家:Javascript 如何在MongoDB中按引用字段查询?,javascript,node.js,mongodb,mongoose,aggregation-framework,Javascript,Node.js,Mongodb,Mongoose,Aggregation Framework,我有两个Mongo模式: 用户: 国家: { _id: ObjectId, name: String } 我想获得所有国家名为“越南”的用户 对于这种情况,我可以使用哪种查询(仅针对用户架构) 我希望它看起来像以下SQL查询: SELECT * FROM User JOIN Country ON User.country = Country._id WHERE Country.name = 'VietNam' 与关系数据库不同,这不是Mongo擅长的,当您使用NoSQL时,通常
{
_id: ObjectId,
name: String
}
我想获得所有国家名为“越南”的用户
对于这种情况,我可以使用哪种查询(仅针对用户架构)
我希望它看起来像以下SQL查询:
SELECT *
FROM User
JOIN Country
ON User.country = Country._id
WHERE Country.name = 'VietNam'
与关系数据库不同,这不是Mongo擅长的,当您使用NoSQL时,通常应该以不同的方式构造模式。在这种情况下,您可以将
countryName
字段添加到user
集合中(可能还有国家索引),以便查询{countryName:“越南”}
。(使用iso-2国家代码可能比使用国家名称更有意义)
如果您确实需要进行“连接”,您可以使用--请记住,聚合的伸缩性不好,而且往往有点难以编写。以下是我通常使用的代码: Models/users.js
const mongoose = require("mongoose");
const Countries = require("./countries");
const UsersSchema = new mongoose.Schema({
name: Sting,
country: Countries.schema
});
module.exports = mongoose.model("Users", UsersSchema);
const express = require("express");
const router = express.Router();
const Users = require("../models/users");
router.post("/register", async(req, res) => {
try{
const Me = await Users.create({name: req.body.name, country: req.body.country})
/* If you make the request correctly on the frontend req.body.name is a
string and req.body.country is an object with one property, it's name */
res.status(200).json({
data: Me
});
}
catch(err){
res.status(400).json({message:err.message})
controllers/users.js
const mongoose = require("mongoose");
const Countries = require("./countries");
const UsersSchema = new mongoose.Schema({
name: Sting,
country: Countries.schema
});
module.exports = mongoose.model("Users", UsersSchema);
const express = require("express");
const router = express.Router();
const Users = require("../models/users");
router.post("/register", async(req, res) => {
try{
const Me = await Users.create({name: req.body.name, country: req.body.country})
/* If you make the request correctly on the frontend req.body.name is a
string and req.body.country is an object with one property, it's name */
res.status(200).json({
data: Me
});
}
catch(err){
res.status(400).json({message:err.message})
因为子模式是一个对象,所以将其引用为Me.country.name。希望这有帮助 您可以将下面的聚合与mongodb3.6及以上版本一起使用
db.country.aggregate([
{ "$match": { "name": "VietNam" } },
{ "$lookup": {
"from": Users.collection.name,
"let": { "countryId": "$_id" },
"pipeline": [
{ "$match": { "$expr": { "$eq": [ "$country", "$$countryId" ] } } },
],
"as": "users",
}},
{ "$unwind": "$users" },
{ "$replaceRoot": { "newRoot": "$users" }}
])
如果要关联2个或多个集合,则必须定义集合的引用对象
我的解决方案请检查此以便在我更新countryId A的国家名称时。我必须找到所有具有countryId A的用户记录,并更新所有记录??性能没问题国家名称(或iso-2国家代码)更改的频率是多少?更新所有用户实体是一项非常昂贵的操作,但这种操作很少发生(并且可以通过让应用程序端代码进行重命名来避免)。对每个查询进行额外的查找最终会花费更高的成本。但是对于通常需要更改的记录,您通常需要在mongo中对数据进行非规范化处理&这项工作的一部分通常涉及确保多个文档保持同步。如果记录经常更改,使用$lookup可以让您返回来自不同集合的文档。如何构造数据和查询在很大程度上取决于您的用例。但我想保留2个模式,用户只存储国家Id,而不是国家对象。由于国家/地区集合将用于显示列表国家/地区,因此应将其分隔为2个模式。主要的问题是,我不知道如何按国家/地区名称向用户查询,您仍然有2个文档集合,但如果您想按国家/地区调用用户,则需要
Users.findMany({country:req.body.country})
。我猜我看错了你的问题,但这是一个很好的参考MongoDB的所有东西。效果很好。但是我可以将user.name='Anthony'和country.name='Vietname'这两个条件组合起来吗?