Mongoose -查询以从多个集合获取数据

dojqjjoe  于 2023-02-23  发布在  Go
关注(0)|答案(6)|浏览(236)

我想***在nodejs应用程序中查询mongoose***,如下所述输出。
js、comment.js和post.js是我使用的模型文件。

    • 用户. 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;
    • 评论. 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'});
    • 邮政. 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",

如果查询是不可能的,请建议我一个适当的mongoose插件。但我不想在user.js文件和它的userSchema对象的任何变化。

wa7juj8i

wa7juj8i1#

Mongo中没有“joins”。但是你要做的是改变你的用户模式,将评论和帖子文档的ObjectId存储在你的用户数组中。然后在你需要用户数据时使用“populate”。

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

qgelzfjb

qgelzfjb2#

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

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

xhv8bpkk3#

当然这是可能的,你只需要使用populate,让我告诉你如何:
导入模式

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

通过这种方式,你可以让用户了解你的评论和帖子,为了让帖子和评论了解用户,你必须执行3个查询,一个针对用户,一个针对评论,一个针对帖子,然后将所有查询混合在一起

csbfibhn

csbfibhn4#

你可以考虑在User模型中使用populate virtual来填充评论和帖子,比如docs(https://mongoosejs.com/docs/populate.html#populate-virtuals)。User.find({filter}).populates('virtualComments').populate('virtualPosts')

1qczuiv0

1qczuiv05#

除了以上回答之外:**如果我们只想为填充的文档返回几个特定的字段,该怎么办?**这可以通过将常用的字段名语法作为第二个参数传递给populate方法来实现:

Story.
  findOne({ title: /casino royale/i }).
  populate('author', 'name'). // only return the Persons name
  exec(function (err, story) {
    if (err) return handleError(err);

    console.log('The author is %s', story.author.name);
    // prints "The author is Ian Fleming"

    console.log('The authors age is %s', story.author.age);
    // prints "The authors age is null"
  });

参考:https://mongoosejs.com/docs/populate.html#field-selection

qnzebej0

qnzebej06#

使用聚合可以在单个查询中完成工作,这几乎与连接类似。

var mongoose = require('mongoose');
var userModel = require('./user');//import user model file
let result = await userModel.aggregate([
  {
    $match: {
      user: mongoose.Types.ObjectId(req.body.user_id),//pass the user id
    }
  },
  {
    $lookup: {
      from: "comments",//your schema name from mongoDB
      localField: "_id", //user_id from user(main) model
      foreignField: "user_id",//user_id from user(sub) model
      pipeline: [ 
        {
          $project:{ //use to select the fileds you want to select
            comment:1, //:1 will select the field
            is_active :1,
            _id:0,//:0 will not select the field
          }
        }
      ],
      as: "comments",//result var name
    }
  },
   {
    $lookup: {
      from: "post",//your schema name from mongoDB
      localField: "_id", //user_id from user(main) model
      foreignField: "user_id",//user_id from user(sub) model
       pipeline: [
        {
          $project:{//use to select the fileds you want to select
            post:1,//:1 will select the field
            is_active :1,
              _id:0,//:0 will not select the field
          }
        }
      ],
      as: "posts",//result var name
    }
  },
  {
    $project:{//use to select the fileds you want to select
      nick_name:1,//:1 will select the field
      email:1,
      _id:0,//:0 will not select the field
      comments:1,
      posts:1
    }
  }
])

相关问题