我有以下mongodb结构:
{
(...)
"services": {
"TCP80": {
"data": [{
"status": 1,
"delay": 3.87,
"ts": 1308056460
},{
"status": 1,
"delay": 2.83,
"ts": 1308058080
},{
"status": 1,
"delay": 5.77,
"ts": 1308060720
}]
}
}}
现在,以下查询返回整个文档:
{ 'services.TCP80.data.ts':{$gt:1308067020} }
我想知道 - 我是否可以只接收符合$ gt条件的那些“数据”数组条目(缩小文档的种类)?
我正在考虑MapReduce,但是找不到一个关于如何将外部参数(timestamp)传递给Map()函数的示例。 (此功能已添加到1.1.4 https://jira.mongodb.org/browse/SERVER-401)
中此外,总有一种替代方法可以编写storedJs函数,但由于我们说的是大量数据,因此这里不能容忍db-locks。
我很可能需要将结构重新设计为1级深度,例如:
{
status:1,delay:3.87,ts:138056460,service:TCP80
},{
status:1,delay:2.83,ts:1308058080,service:TCP80
},{
status:1,delay:5.77,ts:1308060720,service:TCP80
}
但是DB会大幅增长,因为“服务”只是附加每个文档的众多选项之一。
请咨询!
提前致谢
答案 0 :(得分:2)
在带有聚合框架的2.1版中,您现在可以执行此操作:
1: db.test.aggregate(
2: {$match : {}},
3: {$unwind: "$services.TCP80.data"},
4: {$match: {"services.TCP80.data.ts": {$gte: 1308060720}}}
5: );
您可以使用第2行中的自定义条件来过滤父文档。如果您不想过滤它们,只需将第2行留下即可。
答案 1 :(得分:1)
目前不支持此功能。默认情况下,除非使用字段限制或$ slice运算符,否则将始终接收整个文档/数组。目前,这些工具不允许根据搜索条件过滤数组元素。
您应该观看此请求以获取此方法:https://jira.mongodb.org/browse/SERVER-828
答案 2 :(得分:0)
我正在尝试做类似的事情。我尝试过使用GROUP函数的建议,但是我无法将嵌入的文档分开或者做错了。
我需要按ID提取/获取嵌入文档的子集。以下是我使用Map / Reduce进行的方式:
db.parent.mapReduce(
function(parent_id, child_ids){
if(this._id == parent_id)
emit(this._id, {children: this.children, ids: child_ids})
},
function(key, values){
var toReturn = [];
values[0].children.forEach(function(child){
if(values[0].ids.indexOf(product._id.toString()) != -1)
toReturn.push(child);
});
return {children: toReturn};
},
{
mapparams: [
"4d93b112c68c993eae000001", //example parent id
["4d97963ec68c99528d000007", "4debbfd5c68c991bba000014"] //example embedded children ids
]
}
).find()
我已将我的收藏名称抽象为“父级”,并将其嵌入的文档抽象为“子级”。我传入两个参数:父文档ID和我想从父级检索的嵌入式文档ID的数组。这些参数作为第三个参数传递给mapReduce函数。
在map函数中,我在集合中找到父文档(我很确定使用_id索引)并将其id和子元素发送到reduce函数。
在reduce函数中,我获取传入的文档并遍历每个子节点,收集具有所需ID的子节点。循环遍历所有孩子并不理想,但我不知道在嵌入式文档中通过ID查找的另一种方法。
我还假设在reduce函数中,因为我在ID搜索时只发出了一个文档。如果您希望匹配多个parent_id,则必须循环使用reduce函数中的values
数组。
我希望这可以帮助那里的人,因为我在谷歌搜索没有任何结果。希望很快我们会看到MongoDB的内置功能,但在此之前我必须使用它。
答案 3 :(得分:0)
Fadi,至于“将嵌入式文件分开” - 小组应该处理这个没有问题
function getServiceData(collection, criteria) {
var res=db[collection].group({
cond: criteria,
initial: {vals:[],globalVar:0},
reduce: function(doc, out) {
if (out.globalVar%2==0)
out.vals.push({doc.whatever.kind.and.depth);
out.globalVar++;
},
finalize: function(out) {
if (vals.length==0)
out.vals='sorry, no data';
return out.vals;
}
});
return res[0];
};