Javascript 返回不存在数据的零计数
我的mongodb数据收集中的文档遵循此格式Javascript 返回不存在数据的零计数,javascript,node.js,mongodb,mongodb-query,aggregation-framework,Javascript,Node.js,Mongodb,Mongodb Query,Aggregation Framework,我的mongodb数据收集中的文档遵循此格式 [ { "_id": xxxxxxxxx, "crime_type": "illegal_trade", "crime_year": "2013", "location": "Kurunegala" }, { "_id": xxxxxxxxx, "crime_type": "illegal_trade", "crime_year": "2013", "location":
[
{
"_id": xxxxxxxxx,
"crime_type": "illegal_trade",
"crime_year": "2013",
"location": "Kurunegala"
},
{
"_id": xxxxxxxxx,
"crime_type": "illegal_trade",
"crime_year": "2013",
"location": "Colombo"
},
{
"_id": xxxxxxxxx,
"crime_type": "illegal_trade",
"crime_year": "2014",
"location": "Kandy"
},
{
"_id": xxxxxxxxx,
"crime_type": "murder",
"crime_year": "2013",
"location": "Kadawatha"
}
]
当我运行此聚合操作时
db.collection.aggregate(
[
{ $group : { _id : {type: "$crime_type", year: "$crime_year"}, count: { $sum: 1 } } }
]
)
结果仅包含count>0
例如,\u id:{type:“谋杀”,year:“2014”}
的结果,其中count=0
不会包含在结果中
我的问题是,,
我应该如何更改查询,使那些count=0
项也出现在结果中?
换句话说,如何使用mongodb…?基本上,您需要的是数据中不存在的结果,因此如果该组合键不存在,则返回0计数。事实上,没有一个数据库系统“真正”做到这一点,但有一些方法可以让它看起来像正在发生的事情。但这也意味着要了解到底发生了什么,才能做到这一点 确实,SQL方法是从不同的值对预期的键进行子查询,然后将其“连接”到现有数据集,以便为分组累积创建“误报”。这是这里的一般方法,但是当然有一个基本的“连接”概念,由于可伸缩性的原因,MongoDB不支持这个概念。完全不同的论点是,只要接受MongoDB不在自己的服务器架构上进行连接,而且很可能永远不会
这样,在使用MangGDB时创建“假集”的任务被降级到客户端(并且仅考虑“客户端”这一点是对数据库服务器)操作的单独过程。因此,您基本上可以同时获得“结果集”和“空白集”以及“合并”结果
不同的语言方法各不相同,但下面是node.js的有效列表:var async = require('async'),
mongo = require('mongodb'),
MongoClient = mongo.MongoClient,
DataStore = require('nedb'),
combined = new DataStore();
var data = [
{
"crime_type": "illegal_trade",
"crime_year": "2013",
"location": "Kurunegala"
},
{
"crime_type": "illegal_trade",
"crime_year": "2013",
"location": "Colombo"
},
{
"crime_type": "illegal_trade",
"crime_year": "2014",
"location": "Kandy"
},
{
"crime_type": "murder",
"crime_year": "2013",
"location": "Kadawatha"
}
];
MongoClient.connect('mongodb://localhost/test',function(err,db) {
if (err) throw err;
db.collection('mytest',function(err,collection) {
if (err) throw err;
async.series(
[
// Clear collection
function(callback) {
console.log("Dropping..\n");
collection.remove({},callback);
},
// Insert data
function(callback) {
console.log("Inserting..\n");
collection.insert(data,callback);
},
// Run parallel merge
function(callback) {
console.log("Merging..\n");
async.parallel(
[
// Blank Distincts
function(callback) {
collection.distinct("crime_year",function(err,years) {
if (err) callback(err);
async.each( years, function(year,callback) {
collection.distinct("crime_type",function(err,types) {
if (err) callback(err);
async.each( types, function(type,callback) {
combined.update(
{ "type": type, "year": year },
{ "$inc": { "count": 0 } },
{ "upsert": true },
callback
);
},callback);
});
},callback);
});
},
// Result distincts
function(callback) {
collection.aggregate(
[
{ "$group": {
"_id": {
"type": "$crime_type",
"year": "$crime_year"
},
"count": { "$sum": 1 }
}}
],
function(err,results) {
async.each( results, function(result, callback) {
combined.update(
{ "type": result._id.type, "year": result._id.year },
{ "$inc": { "count": result.count } },
{ "upsert": true },
callback
);
},callback);
}
);
}
],
function(err) {
callback(err);
}
)
},
// Retrieve result
function(callback) {
console.log("Fetching:\n");
combined.find({},{ "_id": 0 }).sort(
{ "year": 1, "type": 1 }).exec(function(err,results) {
if (err) callback(err);
console.log( JSON.stringify( results, undefined, 4 ) );
callback();
});
}
],
function(err) {
if (err) throw err;
db.close();
}
)
});
});
这将返回一个结果,该结果不仅“合并”分组密钥的结果,而且还包含“2014年”中“谋杀”的0
条目:
考虑操作的本质在这里,主要是在“合并”下的代码的“并行”部分中,因为这是一种有效的方式来同时发出所有的查询(并且可能有相当多的查询)。 为了获得不计数的“空白”结果,第一部分基本上是一个双循环操作,其要点是获得“年”和“类型”的不同值。无论您是使用此处所示的方法,还是使用带有“游标”的方法进行输出和迭代,都取决于您拥有多少数据或您个人喜欢什么。对于一个小集合,生成
.distinct()
,结果在内存中就可以了。但我们希望为每个可能的配对创建“空白”或0
count条目,或者更重要的是将那些“不存在”的条目作为配对包含在数据集中
其次,在可能的情况下,聚合结果与标准结果并行运行。当然,这些结果不会返回“2014年”的“谋杀”罪名,因为根本没有。但这基本上可以归结为合并结果
“merge”基本上是使用“hash/map/dict”(不管你的术语是什么),即“year”和“type”的组合键。因此,您只需使用该结构,在不存在该键的地方添加该键,或者在存在该键的地方增加该键的“count”值。这是一个由来已久的操作,本质上是所有聚合技术的基础
这里要做的一件简单的事情(不是你需要使用它)是使用,它是一个很好的小模块,允许在内存或其他自包含的数据文件上使用MongoDB“类似”操作。将其视为SQLite到SQLRDBMS操作。在整个功能上只需要稍微轻一点
这里的一部分要点是“散列合并”函数现在看起来像代码中的常规MongoDB操作。事实上,如果您有一个大的结果需要在服务器上的“结果集合”中结束,那么同样的代码基本上也适用
总的来说,这实际上是一个“连接”操作,或者是一个“填空”操作,具体取决于操作中“键”的总体大小和期望值。MongoDB服务器不会这样做,但没有任何东西可以阻止您编写自己的“数据层”,作为最终应用程序和数据库之间的中间层。这样的分布式服务器模型可以扩展,以便该服务级别执行这些类型的“连接”操作
用于获取要合并的数据的所有查询都可以在正确的编码环境下有效地并行运行,因此,尽管这看起来不像SQL方法那样简单,但在实际处理结果时仍然非常有效
方法不同,但这也是这里哲学的一部分。MongoDB将“加入”活动重新放在应用程序体系结构的不同部分,以保持其自身特定于服务器的操作更高效,主要是针对分片集群。“加入”或此“散列合并”是一个“代码”函数,可由数据库服务器以外的其他基础结构处理。您的文档以{{}开头。它是一个文档还是多个文档?@Disposer multiple docs.。我尝试了您的查询,得到了以下结果:{“结果”:[{u id:{“类型”:“谋杀”,“年份”:“2013”},“计数”:1},{U id:{“类型”:“非法交易”,“年份”:“2014”},“计数”:1},{U id:{“类型”:“非法交易”,“年份”:“2013”},“count”:2}],“ok”:1}是的,它可以工作。但是我希望结果也包括
“count”:0
项。
[
{
"type": "illegal_trade",
"year": "2013",
"count": 2
},
{
"type": "murder",
"year": "2013",
"count": 1
},
{
"type": "illegal_trade",
"year": "2014",
"count": 1
},
{
"type": "murder",
"year": "2014",
"count": 0
}
]