Сохранение вложенных объектов в мангусте
Я новичок в node.js и MongoDb (и базы данных документов в целом), так голый со мной. Исходя из фона PHP/MySQL, я борюсь с лучшими практиками в плане структурирования и сохранения моих данных.
Я пытаюсь создать небольшое приложение, где я могу добавлять рецепты с несколькими ингредиентами. У меня есть куча предварительно заполненных ингредиентов в качестве исходных данных, схема, для которой выглядит:
var IngredientSchema = new Schema({
name: {
type: String,
trim: true,
required: true,
index: {
unique: true
}
},
created: {
type: Date,
default: Date.now
}
});
var Ingredient = mongoose.model('Ingredient', IngredientSchema);
В настоящее время рецепт выглядит следующим образом:
var RecipeSchema = new Schema({
name: {
type: String,
trim: true
},
ingredients: [
{
type: Schema.Types.ObjectId,
ref: 'RecipeIngredient'
}
],
created: {
type: Date,
default: Date.now
}
});
var Recipe = mongoose.model('Recipe', RecipeSchema);
Наконец, у меня есть RecipeIngredientSchema. Теперь, где мой фоновый фон MySQL может быть ползком; причина, по которой я это делал, заключается в том, что я хочу, чтобы между разными рецептами и ингредиентами было много отношений, но я также хочу указать единицу:
var RecipeIngredientSchema = new Schema({
recipe: {
type: Schema.Types.ObjectId,
ref: 'Recipe'
},
ingredient: {
type: Schema.Types.ObjectId,
ref: 'Ingredient'
},
unit: {
type: Schema.Types.ObjectId,
ref: 'Unit'
},
created: {
type: Date,
default: Date.now
}
});
var RecipeIngredient = mongoose.model('RecipeIngredient', RecipeIngredientSchema);
Мой вопрос состоит из двух частей:
- Я собираюсь сделать это разумным способом с точки зрения моделирования данных или с пути?
- Как бы выглядел процесс сохранения рецепта с несколькими ингредиентами?
В настоящее время я думаю следующее:
exports.create = function(req, res) {
var recipe = new Recipe(req.body);
recipe.save(function(err, recipe) {
if (err) {
return res.jsonp(err);
} else {
// Loop ingredients
if (req.body.ingredients) {
for(var prop in req.body.ingredients) {
var recipeIngredient = new RecipeIngredient({
recipeId: recipe._id,
ingredientId: mongoose.Types.ObjectId(req.body.ingredients[prop])
});
recipeIngredient.save(function(err, recipeIngredient) {
if (err) {
return res.jsonp(err);
} else {
recipe.recipeIngredients.push(recipeIngredient._id);
recipe.save(function(err, recipe) {
return res.jsonp(recipe);
});
}
});
};
}
}
});
}
Я чувствую, что это запутанно и, как правило, неправильно, поэтому было бы полезно получить какое-то руководство!
Ответы
Ответ 1
Красота баз данных NoSQL (или хранилищ документов в целом) заключается в том, что вам не нужно разделить свои данные на несколько таблиц/коллекций. Вы можете хранить все связанные данные в одном объекте, чтобы ваши операции чтения выполнялись одним выстрелом.
Для этого не существует "правильного" подхода, но если вы собираетесь использовать NoSQL, я бы рассмотрел возможность сохранения всего рецепта (рецепта, ингредиентов и указаний) как одного документа, а не разделения данных на 3 или 4 таблицы a-la реляционная модель.
Например, я бы сохранил один рецепт следующим образом:
recipe = {
name: 'name of recipe'
time: '45 minutes'
ingredients : [
{qty: 3, unit: 'item', name: 'tomatoes'},
{qty: 0.5, unit: 'tbs', name: 'salt'},
{qty: 1, name: 'item', name: 'avocado'}
]
}
Теперь это не пыль. Будут времена, когда данные, разделенные на несколько таблиц/коллекций и имеющие реляционный язык запросов (например, SQL), будут полезны для запроса данных. Например, если вы хотите запросить все рецепты, которые используют "томаты", имеющие реляционную базу данных с таблицей соединений для отношений рецепта/ингредиентов, это значительно упростит, чем подход NoSQL.
Это решение, которое вам нужно будет сделать в какой-то момент: лучше ли вы с NoSQL или с RBMS для вашего приложения?
Ответ 2
Если вы хотите сохранить вложенные объекты в БД, у вас есть два варианта: встроенная схема или ссылка. Если вы сохраните их, указав их, вложенная схема будет сохранена в отдельной коллекции.
Начните смотреть на этот пример mongo-many-to-many и этот раздел: save-refs