实验室简明mongoDB用户体验指南·续——查询
上篇: 2015-12-22 blog: 从MongoDB入门到编写数据库相关API
本指南延续上篇的内容,带领大家使用MongoDB Node.js Driver进行应用开发。 Node.js Driver与Mongoose之间的关系
可以的话,我们重新来过。
可以的话,要我弥补他犯的错。
1. 操作类型
Find——基本查询
- find <-> select
shell: db.collection.find(
, )
- 与RDBMS比较:
query filter <-> where condition
Projection <-> select field
- 在Driver中的写法有点不同:
db.collection(‘dbo.TBL_FAULT_INFO’).find(
, )
那么我们的分页排序等操作呢?
- 链式调用
Obj.method1().method2()……
而异步操作一般会向最后一个函数传入回调函数处理操作结果,like this:
db.collection('dbo.TBL_FAULT_INFO')
.find({ 'EVENT_NAME': { $ne: null }, 'INFO_TIME': { $ne: null } }, { '_id': 0, 'INFO_TIME': 1, 'EVENT_NAME': 1 })
.limit(1000)
.sort({ 'INFO_TIME': 1 })
.toArray(function (err, result) {
if (err) {
cb(err);
} else {
cb(null, result);
}
});
与之相同效果的SQL 查询:
SELECT TOP 1000 INFO_TIME, EVENT_NAME
FROM dbo.TBL_FAULT_INFO
WHERE EVENT_NAME IS NOT NULL and INFO_TIME IS NOT NULL
ORDER BY INFO_TIME ASC
两者之间的映射关系:
And more, 查询操作的其他处理方法可查阅,外援:Node.js Driver 查询操作
Aggregation——聚合操作
聚合操作就是将集合中的数据按步骤进行处理,是一种比MapReduce容易操作的批处理计算方法。
引入外援: 2016-03-03 blog: MongoDB Aggregation实践
在MongoDB 3.2之后,官方将聚合管道和Map-Reduce计算模型统称Aggregation。在我们的上下文中,还是将Aggregation限制为以.aggregate()方法为内容的计算功能。
方法
在 db.collection.aggregate
方法中,以数组的方式传递每个stage。集合中的文档会按序传递到这些stages。
db.collection('dbo.TBL_FAULT_INFO')
.aggregate([
{ // match stage
$match: {
'INFO_TIME': select_fault_time
}
},
{ // group stage
$group: {
'_id': '$INFO_TIME',
'counttime': { $sum: 1 }
}
},
{ // limit stage
$limit: 1000
}
], function (err, result) {
if (err) {
cb(err);
} else {
cb(null, result);
}
});
在这里以思维导图的方式讲解我们会用到的stage。
思维导图原图 其他stage方法请看,外援: Aggregation stages
2. 常见解决方案
IS NOT NULL
的条件
非空条件分为两种情况:一个是空字段,一个是内嵌空数组。我们将使用$ne表达式过滤数据,$ne的意思就是 not equal 。
{
$match: {
'DEBUG_CONDITION': { $ne: null }
}
}
而过滤空数据只需要修改一个地方。
{
$match: {
'DEBUG_CONDITION': { $ne: [] }
}
}
依据时间字段进行过滤
在$match stage中使用$gt(greater than)、$lt(less than)等操作符来过滤。而Javascript是MongoDB的查询语言,我们可以通过JS的Date对象来操作时间字段。
{
$match: {
'insert_time': { $gt: new Date('2015-08-01T00:00:00.000Z') },
'EVENT_TYPE': 1
}
}
内联结和左外联结的问题
内联结是什么
内联结:查询会将 A 表的每一行和 B 表的每一行进行比较,并找出满足连接谓词的组合。当连接谓词被满足,A 和 B 中匹配的行会按列组合(并排组合)成结果集中的一行。
左外联结是什么
若 A 和 B 两表进行左外连接, 那么结果表中将包含"左表"(即表 A)的所有记录,即使那些记录在"右表" B 没有符合连接条件的匹配。
SQL中JOIN默认为内联结,比如下列联结条件会将A、B表中满足A.NETNODE_NAME = B.net_node_name
条件的记录合并成一行记录。
JOIN dbo.TBL_NETNODE_INFO B ON A.NETNODE_NAME = B.net_node_name
那么在只有左外联结的MongoDB操作中就只能通过手动将A表多余的数据过滤掉。我们首先将空数组过滤,并将数组展开与原集合组合。
{
$lookup: {
from: 'dbo.TBL_NETNODE_INFO',
localField: 'NETNODE_NAME',
foreignField: 'net_node_name',
as: 'netnodes'
}
},
{
$match: {
'netnodes': { $ne: [] }
}
},
{
$unwind: '$netnodes'
},
分组聚合统计次数的方法
在一个场景中需要依据时间字段统计每日的记录数。
使用$substr
可以对时间字符串进行截取,这里截取10个字符,也就是 ‘2016-12-31’ 。
{
$group: {
'_id': { $substr: ['$DEAL_TIME', 0, 10] },
'COUNT_TIME': { $sum: 1 }
}
}
索引导致的Error
这种情况一般出现在对集合进行排序时。由于没有索引的帮助,排序会将所有字段写入内存中。在集合数据量大时,占用的内存会达到32mb的限制。
解决方法就是创建相应的索引。
3. Q&A
答案一直到今天,才在我心中浮现。 那一瞬间 我们都没发现