MongoDB-插入到两个集合中,一个集合引用另一个作为子文档
MongoDB - insert into two collections, one collection referencing the other as subdocument
Meteor和MongoDB的新功能,来自关系数据库背景。这个问题实际上反映了我对MongoDB中如何处理关系的困惑。
示例:我想将一个食谱插入一个食谱集合中,在本例中,它是一个由多个成分组成的逗号分隔字符串。然而,我想同时将这些成分插入一组成分中。我想让食谱参考配料集合中的配料,这样,如果我第一次拼写错误,我可以稍后在配料集合中更新它,并更新所有使用该配料的食谱。
似乎这样做的方法是将配料集合作为子文档包含在配方集合中。
然而,我不确定如何才能真正实现这一点。使用Meteor的JS中的示例代码如下:
Recipes = new Mongo.Collection("recipes");
Ingredients = new Mongo.Collection("ingredients");
Template.body.events({
"submit .new-recipe": function(event) {
// Prevent default browser form submit
event.preventDefault();
// Get value from form element
var text = event.target.text.value;
var splitText = text.split(",");
var nInputs = splitText.length;
var recipe = [];
for (var i = 0; i < nInputs; i++) {
// Insert an ingredient into the ingredients collection
Ingredients.insert({
itemName: splitText[i].trim(),
createdAt: new Date()
});
recipe.push(splitText[i]);
}
// Insert the list of ingredients as a recipe into the recipes collection
Recipes.insert({
recipe: recipe,
createdAt: new Date()
});
// Clear form
event.target.text.value = "";
}
});
显然,以上内容不能正确地完成任务。它切断了配料和食谱之间的关系。但是我该如何维持这种关系呢?在插入配料时,我是否将配料的ID放入食谱集合?在插入配料时,我是否将整个配料文档作为配方文档的一部分插入到配方集合中?
听起来您需要在两个集合之间建立一个简单的关系模型。这通常是通过将一个集合的_id
作为值存储在另一个集合中来实现的。在您的情况下,我建议将成分id作为数组存储在配方中。我看到你最初尝试的一些问题:
-
在插入之前没有检查成分的存在。所以两个使用"糖"的食谱会插入两个糖文档——我想这不是你的本意。
-
插入是在客户端上进行的,但除非您发布整个成分集合,否则客户端不能是实际存在哪些成分的权威(从1开始)。
-
在执行插入操作时,您使用的是客户端的时间戳。如果他们的时钟错了怎么办?实际上有一个包可以处理这个问题,但我们可以使用一种方法来解决以上所有问题。
我建议拆分客户端上的文本输入,然后发出Meteor.call('recipes.insert', ingredientNames)
,其中方法实现看起来像这样:
Meteor.methods({
'recipes.insert': function(ingredientNames) {
// Make sure the input is an array of strings.
check(ingredientNames, [String]);
// Use the same createdAt for all inserted documents.
var createdAt = new Date;
// Build an array of ingredient ids based on the input names.
var ingredientIds = _.map(ingredientNames, function(ingredientName) {
// Trim the input - consider toLowerCase also?
var name = ingredientName.trim();
// Check if an ingredient with this name already exists.
var ingredient = Ingrediends.findOne({itemName: name});
if (ingredient) {
// Yes - use its id.
return ingredient._id;
} else {
// Insert a new document and return its id.
return Ingrediends.insert({
itemName: name,
createdAt: createdAt
});
}
});
// Insert a new recipe using the ingredient ids to join the
// two collections.
return Recipes.insert({
ingredientIds: ingredientIds,
createdAt: createdAt
});
}
});
推荐阅读:
- 这个关于流星中关系模型的问题
- Meteor:访问另一个集合,每个块中有一个id
- 另一个集合视图中的集合视图
- 如何使用Angular 2服务提供包含指向另一个资源的链接/ids的资源集合
- Mongo-Aggregate:如何与另一个集合中的字段进行比较
- Meteor - 将 mongodb 查询分配给变量并将其插入到另一个集合
- 基于 MongoDB 中另一个集合中的数据查询一个集合中的数据
- 流星 - 将数据从一个集合移动到另一个集合
- 如何在插入时引用另一个集合
- 我应该如何创建一个作用域到另一个模型的主干集合
- 主干:将模型从一个集合添加到另一个集合
- 用于将树分支从集合移动到另一个集合的Firebase API
- 在Meteor(MongoDB)中,按另一个集合中的值搜索一个集合
- MongoDB-插入到两个集合中,一个集合引用另一个作为子文档
- Meteor从数组返回值,以便在另一个集合中使用它
- Restangular:将元素从一个集合插入到具有不同路线的另一个集合
- 在backbone.js中将一个集合添加到另一个集合中
- 发送多个数组到骨干集合,渲染一个,保存另一个
- 在另一个集合中存储引用会创建对象,但不会创建字符串Meteor
- 如何将集合发送到另一个视图
- 当发布的游标基于另一个集合内容时,如何构建响应式发布