reduce = function(k, values) {
var result = {};
values.forEach(function(value) {
var field;
for (field in value) {
if (value.hasOwnProperty(field)) {
result[field] = value[field];
}
}
});
return result;
};
如果你想展平 users_comments 集合,那么它是每个评论的一个文档,另外运行:
var map, reduce;
map = function() {
var debug = function(value) {
var field;
for (field in value) {
print(field + ": " + value[field]);
}
};
debug(this);
var that = this;
if ("comments" in this.value) {
this.value.comments.forEach(function(value) {
emit(value.commentId, {
userId: that._id,
country: that.value.country,
age: that.value.age,
comment: value.comment,
created: value.created,
});
});
}
};
reduce = function(k, values) {
var result = {};
values.forEach(function(value) {
var field;
for (field in value) {
if (value.hasOwnProperty(field)) {
result[field] = value[field];
}
}
});
return result;
};
db.users_comments.mapReduce(map, reduce, {"out": "comments_with_demographics"});
绝对不应该在飞行中执行此技术 . 它's suited for a cron job or something like that which updates the merged data periodically. You' ll可能想要在新集合上运行 ensureIndex 以确保您对它执行的查询运行得很快(请记住,您的数据仍然在 value 键内,所以如果您在注释 created 时间索引 comments_with_demographics ,它会是 db.comments_with_demographics.ensureIndex({"value.created": 1});
9 回答
虽然您无法实时执行此操作,但可以使用MongoDB 1.8 map / reduce中的"reduce" out选项多次运行map-reduce以将数据合并在一起(请参阅http://www.mongodb.org/display/DOCS/MapReduce#MapReduce-Outputoptions) . 您需要在两个集合中都有一些密钥才能用作_id .
例如,假设您有一个
users
集合和一个comments
集合,并且您希望拥有一个新集合,其中包含每个评论的一些用户人口统计信息 .假设
users
集合包含以下字段:_id
firstName
lastName
国家
性别
年龄
然后
comments
集合包含以下字段:_id
userId
评论
已创建
你会做这个map / reduce:
此时,您将拥有一个名为
users_comments
的新集合,其中包含合并的数据,您现在可以使用它 . 这些缩小的集合都有_id
,这是您在 Map 函数中发出的关键,然后所有值都是value
键中的子对象 - 这些值不在这些缩小文档的顶层 .这是一个有点简单的例子 . 您可以使用更多集合重复此操作,以便继续构建简化集合 . 您还可以在此过程中对数据进行摘要和聚合 . 可能您会定义多个reduce函数,因为聚合和保留现有字段的逻辑变得更加复杂 .
您还会注意到,现在每个用户都有一个文档,其中包含该用户在数组中的所有注释 . 如果我们合并具有一对一关系而不是一对多关系的数据,那么它将是平坦的,您可以简单地使用如下的reduce函数:
如果你想展平
users_comments
集合,那么它是每个评论的一个文档,另外运行:绝对不应该在飞行中执行此技术 . 它's suited for a cron job or something like that which updates the merged data periodically. You' ll可能想要在新集合上运行
ensureIndex
以确保您对它执行的查询运行得很快(请记住,您的数据仍然在value
键内,所以如果您在注释created
时间索引comments_with_demographics
,它会是db.comments_with_demographics.ensureIndex({"value.created": 1});
MongoDB 3.2现在允许通过$lookup aggregation stage将来自多个集合的数据合并为一个 . 作为一个实际的例子,假设你有关于书籍的数据分成两个不同的集合 .
第一个集合,名为
books
,具有以下数据:第二个集合名为
books_selling_data
,具有以下数据:合并两个集合只需要通过以下方式使用$ lookup:
在此聚合之后,
books
集合将如下所示:重要的是要注意以下几点:
"from"集合,在本例中为
books_selling_data
,无法分片 ."as"字段将是一个数组,如上例所示 .
$lookup stage上的"localField"和"foreignField"选项如果在各自的集合中不存在,则会被视为空,以便进行匹配($lookup docs有一个完美的例子) .
因此,作为一个结论,如果你想整合两个集合,在这种情况下,拥有一个平面的copy_sold字段和销售的总副本,你将需要更多的工作,可能使用一个中间集合,然后,是$out到最后的收藏 .
如果mongodb中没有批量插入,我们循环
small_collection
中的所有对象并将它们逐个插入到_745696中:$ lookup的非常基本的例子 .
这是用的
代替
因为如果找不到与$ lookup匹配的记录, { $unwind:"$userRoleData"} 将返回空或0结果 .
在聚合中为多个集合使用多个 $lookup
query:
result:
Mongorestore具有附加在数据库中已有的任何内容之上的功能,因此这种行为可用于组合两个集合:
mongodump collection1
collection2.rename(collection1)
mongorestore
还没试过,但它可能比map / reduce方法执行得更快 .
代码段 . 礼貌 - 堆栈溢出的多个帖子,包括这个 .
是的你可以:采取我今天写的这个实用功能:
您可以将任意数量的集合传递给此函数,第一个集合将成为目标集合 . 所有其余的集合都是要转移到目标集合的源 .
您've to do that in your application layer. If you'使用ORM,它可以使用注释(或类似的东西)来提取其他集合中存在的引用 . 我只有使用Morphia,@Reference注释在查询时获取引用的实体,因此我可以避免在代码中自己执行此操作 .