【问题标题】:Mongoose - query to get data from multiple collectionsMongoose - 查询以从多个集合中获取数据
【发布时间】:2016-06-18 03:42:36
【问题描述】:

我想在 nodejs 应用程序中获取猫鼬的查询,如下所述。
user.js、comment.js 和 post.js 是我使用的模型文件。

user.js

var mongoose = require('mongoose');  
var Schema = mongoose.Schema;  
var ObjectId = Schema.ObjectId;  

var userSchema = new Schema({  
        nick_name:{type:String},  
        email: {  
            type: String,  
            trim: true,  
            required: '{PATH} is required!',
            index: true,
        },     
    },{ collection: 'user'});

var User = mongoose.model('User', userSchema);
module.exports = User;  

comment.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var commentSchema = new Schema({  
         comment: type:String,  
         user_id:{
            type:Schema.Types.ObjectId, ref:'User'
         },  
         is_active :1
},{ collection: 'comment'});

post.js

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;

var postSchema = new Schema({
        post: type:String,
        user_id:{
           type:Schema.Types.ObjectId, ref:'User'
        },
        is_active :1
},{ collection: 'post'});

想出来如下:

{
 "nick_name":"prakash",
 "email":"prakash@mailinator.com",
 "comments":[
      {
      "comment":"this is a comment text1",
      "is_active":1,
      },
      {
      "comment":"this is a comment text2",
      "is_active":1,
      }
 ],
 "posts":[
      {
      "post":"this is a post text1",
      "is_active":1,
      },
      {
      "post":"this is a post text2",
      "is_active":1,
      },
      {
      "post":"this is a post text3",
      "is_active":1,
      },
 ]
}

依赖项

"express"  => "version": "4.7.4",
"mongoose" => "version": "4.4.5",
"mongodb"  => "version": "2.4.9",
"OS"  => "ubuntu 14.04 lts 32bit",

如果无法查询,请建议我一个合适的猫鼬插件。 但我不想对 user.js 文件及其 userSchema 对象进行任何更改。

【问题讨论】:

  • @BlakesSeven - 哈哈 Simplez...
  • 我现在也在苦苦挣扎,我有评论对象,Like 对象,还有其他对象。我想向用户个人资料页面显示他所做的所有活动。但关键是它们是不同的集合。如果我单独做,那么它们将不会按时间排序
  • 我确实在“猫鼬的查询”中看到了幽默,但对@laxman 的支持,我只精通一种语言。用英语表达这个你可能会说,'我想在 nodejs 应用程序中使用 Mongoose 查询 Mongo 数据库......'。

标签: node.js mongodb mongoose


【解决方案1】:

当然有可能,你只需要使用填充,让我告诉你如何:

导入您的架构

var mongoose = require('mongoose');
var userSch = require('userSchema');
var postSch = require('postSchema');
var commSch = require('commentSchema');

初始化所有必要的变量

var userModel = mongoose.model('User', userSch);
var postModel = mongoose.model('Post', postSch);
var commModel = mongoose.model('Comment', commSch);

现在,进行查询

postModel.find({}).populate('User')
    .exec(function (error, result) {
        return callback(null, null);
    });

commModel.find({}).populate('User')
    .exec(function (error, result) {
        return callback(null, null);
    }); 

通过这种方式,您可以在您的评论和帖子中获取用户,要在您的用户中获取帖子和 cmets,您必须执行 3 个查询,一个用于用户,一个用于 cmets,一个用于帖子,并混合在一起

【讨论】:

  • 感谢您的回答,但我只想要一个用户集合中的查询
【解决方案2】:

Mongo 中没有“连接”。但是您要做的是更改您的用户模式以将评论和发布文档的 ObjectId 存储在您的用户数组中。然后在需要用户数据时使用“填充”。

const userSchema = new Schema({  
    nick_name:{type:String},  
    email: {  
        type: String,  
        trim: true,  
        required: '{PATH} is required!',
        index: true,
    },
    comments: [{ type: Schema.Types.ObjectId, ref:'Comment' }],
    posts: [{ type: Schema.Types.ObjectId, ref:'Post' }]
}, {timestamps: true});

mongoose.model('User', userSchema);

您的查询将如下所示:

User.find()
    .populate('comments posts') // multiple path names in one requires mongoose >= 3.6
    .exec(function(err, usersDocuments) {
        // handle err
        // usersDocuments formatted as desired
    });

Mongoose populate docs

【讨论】:

  • 这种方法的问题是数组越来越大,你不知道你的 cmets 或帖子数组会增长多少,这会插入另一种探针
  • 存储的数组只包含 ObjectId。除非我遗漏了什么,否则这应该可以扩展。如果我错过了@shontauro,请告诉我。
  • 第二个 ObjectId 有错别字。它会产生运行时错误。
  • 很抱歉。固定。
  • 技术上这是正确的。但是从功能的角度来看,用户应该是一个独立的实体,其中不应该有任何其他信息。因此,所有其他实体(无论何时需要用户 ID)都应将用户 ID 存储为字段之一。可能是用户可以编写一个视图来从多个集合中获取 cmets 和帖子。
【解决方案3】:

有可能。您应该使用聚合。 它应该工作。 初始化变量

    var mongoose = require('mongoose');
    var userCollection = require('./user');//import user model file
    var resources = {
    nick_name: "$nick_name",
    email: "$email"};

    userCollection.aggregate([{
            $group: resources
        }, {
            $lookup: {
                from: "Comments", // collection to join
                localField: "_id",//field from the input documents
                foreignField: "user_id",//field from the documents of the "from" collection
                as: "comments"// output array field
            }
        }, {
            $lookup: {
                from: "Post", // from collection name
                localField: "_id",
                foreignField: "user_id",
                as: "posts"
            }
        }],function (error, data) {
         return res.json(data);
     //handle error case also
});

【讨论】:

    【解决方案4】:

    您可以考虑在模型用户中使用 cmets 和诸如 docs (https://mongoosejs.com/docs/populate.html#populate-virtuals) 之类的帖子的虚拟填充。并像这样使用: User.find({filter}).populates('virtualComments').populate('virtualPosts')

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    猜你喜欢
    • 1970-01-01
    • 2016-06-20
    • 2017-10-22
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    相关资源
    最近更新 更多