在MongoDB中定义3个不同关系的模式(多对多,一对多…)

我在我的应用程序中有3个不同的模式:

userSchema, questionSchema, listingSchema 

三者的关系如下:

每个列表都有很多与其相关的问题(每个列表都有相同的问题)。
每个用户 可以在几个列表中回答很多问题。
许多列表中的许多用户都回答了每个问题

我试图围绕定义这些模式之间的正确关系(主要是因为“ _id = 100用户在_id = 3的列表中回答了_id = 5的问题,我如何更新所有这些最有效的方式?)。

到目前为止,我已经定义:

questionSchema:

 var questionSchema = new Schema({ description: String }); 

userSchema:

 var userSchema = new Schema({ local : { email : String, password : String, name : String }, ApartmentsAndQuestions: [{ apartmentID: String, questionID: [String] /* one apartment -> multiple questions */ }] }); 

和listingSchema:

 var listingSchema = new Schema({ street : String, buildingNumber : Number, apartmentNumber : Number, type : String, floor : Number, outOfFloors : Number, numberOfRooms : Number, size : Number, renovated : Boolean, elevator : Boolean, airConditioning : Boolean, balcony : Boolean, price : Number, description : String, flagCount : Number, pictures : [imageSchema] owner : [userSchema] UsersAndQuestions: [{ userID: String, questionID: [String] /* one user -> multiple questions asked possible */ }] }); 

问题:如何在我的NoSQL数据库中做到这一点? 我的定义是否有意义? 有没有更好的方式来描述这些模式之间的关系?

任何帮助将不胜感激!

你会想要定义你的模式如下:

 var userSchema = mongoose.Schema({ local : { email : String, password : String, name : String }, /* every entry in the array is an apartment ID and the questionsIDs (array) of the questions that the user ALREADY answered in that *specific* apartment */ ApartmentsAndQuestions: [{ apartmentID : String, questionsIDs: [String] }] }); 

和:

 var listingSchema = new Schema({ street : String, buildingNumber : Number, apartmentNumber : Number, type : String, floor : Number, outOfFloors : Number, numberOfRooms : Number, size : Number, renovated : Boolean, elevator : Boolean, airConditioning : Boolean, balcony : Boolean, price : Number, description : String, flagCount : Number, ownerID : String, /* every entry in the array is a userID and the questionsIDs (array) of the questions that the user ALREADY answered in that *specific* apartment */ UsersAndQuestions: [{ userID: String, questionID: [String] }], /* every image has a count of how many times the users answered YES or NO on it */ imagesAndCount: [{ imageID: String, count: Number }] }); 

那么你基本上可以做一些事情:

 var someuser = db.users.find()[2] // get some user 

someuser._id >>> which returns some ObjectId("56472a83bd9fa764158d0cb6")然后: db.users.find({_id: ObjectId("56472a83bd9fa764158d0cb6")}) >>> which will return someuser (with all the fields that are defined in the User schema)

然后: db.listings.insert({"street" : "SomeStreet", "buildingNumber" : 33, "apartmentNumber" : 63, "beds": 3, "owner" : "56472a83bd9fa764158d0cb6"})

上市将如下所示:
现在列表如下所示:

 { "_id": { "$oid": "566c220abcda51a9eef08576" }, "street": "SomeStreet", "buildingNumber": 33, "apartmentNumber": 63, "beds": 3, "owner": "56472a83bd9fa764158d0cb6" } 

MongoDB 3.2+解决scheme

在评论中添加提到,你可以使用新的$ lookup来避免embedded大量的数据。 这就像一个SQL LEFT JOIN:

让我们添加一些与您的匹配的数据:

 db.questionSchema.insert({ _id: 1, description: "My description 1" }); db.questionSchema.insert({ _id: 2, description: "My description 2" }); db.questionSchema.insert({ _id: 3, description: "My description 3" }); db.questionSchema.insert({ _id: 4, description: "My description 4" }); db.userSchema.insert({ _id: 1, email: "my@email1.com", ApartmentsAndQuestions: [] }); db.userSchema.insert({ _id: 2, email: "my@email2.com", ApartmentsAndQuestions: [] }); db.listingSchema.insert({ _id: "A", UsersAndQuestions: [] }) db.listingSchema.insert({ _id: "B", UsersAndQuestions: [] }) // Add some questions db.userSchema.update({ _id: 1 }, { $addToSet: { ApartmentsAndQuestions: { apartment_id: 1, question_id: [1] } } }) db.userSchema.update({ _id: 1, "ApartmentsAndQuestions.apartment_id": 1 }, { $addToSet: { "ApartmentsAndQuestions.$.question_id": 3 } }) db.userSchema.update({ _id: 2 }, { $addToSet: { ApartmentsAndQuestions: { apartment_id: 2, question_id: [1,2] } } }) db.userSchema.update({ _id: 2, "ApartmentsAndQuestions.apartment_id": 2 }, { $addToSet: { "ApartmentsAndQuestions.$.question_id": 4 } }) db.listingSchema.update({ _id: "A" }, { $addToSet: { UsersAndQuestions: { user_id: 1, question_id: [1] } } }) 

定期find,这里是你得到的:

 test> db.listingSchema.find() { "_id": "B", "UsersAndQuestions": [ ] } { "_id": "A", "UsersAndQuestions": [ { "user_id": 1, "question_id": [ 1 ] } ] } 

然后,让我们$ lookup:

 db.listingSchema.aggregate([ { $unwind: "$UsersAndQuestions" } ,{ $lookup: { from: "userSchema", localField: "UsersAndQuestions.user_id", foreignField: "_id", as: "fetched_user" } } ,{ $unwind: "$UsersAndQuestions.question_id" } ,{ $lookup: { from: "questionSchema", localField: "UsersAndQuestions.question_id", foreignField: "_id", as: "fetched_question" } } ]) 

你得到:

 { "waitedMS": NumberLong("0"), "result": [ { "_id": "A", "UsersAndQuestions": { "user_id": 1, "question_id": 1 }, "fetched_user": [ { "_id": 1, "email": "my@email1.com", "ApartmentsAndQuestions": [ { "apartment_id": 1, "question_id": [ 1, 3 ] } ] } ], "fetched_question": [ { "_id": 1, "description": "My description 1" } ] } ], "ok": 1 } 

然后,你也可以解开ApartmentsAndQuestions.questions_id和$查找问题数据。 随你便。