我的应用程序中有3种不同的模式:
userSchema, questionSchema, listingSchema
三者之间的关系如下:
每个列表都有很多与之相关的问题(每个列表都有相同的问题)
每个用户 都可以在多个商家信息中回答许多问题
很多用户都会回答每个问题。
我试图围绕定义这些模式之间的正确关系(主要是因为_id = 100
用户在_id = 5
的商家信息中使用_id = 3
回答了问题,我如何以最有效的方式更新所有这些?)。
到目前为止,我已定义:
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 */
}]
});
并且listSchema:
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数据库中做得好?我的定义有意义吗?有没有更好的方法来描述这些模式之间的关系?
任何帮助都非常赞赏!
答案 0 :(得分:1)
MongoDB 3.2+解决方案
在评论中添加,您可以使用新的$lookup来避免嵌入大量数据。它就像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] } } })
通过常规查找,您可以获得以下内容:
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
和$查询问题数据。它取决于你。
答案 1 :(得分:0)
您需要按如下方式定义架构:
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
>>>返回一些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"
}