MongoDB查询
查找文档无疑是最常见的MongoDB数据库操作。
如何访问MongoDB服务器中的文档。
- 理解Cursor对象的用途;
- 使用Cursor对象访问集合中的文档;
- 查找单个文档;
- 查找多个文档;
- 使用查询运算符根据字段值查找文档;
- 根据子文档字段查找文档。
- 确定与查找操作匹配的文档数;
- 以特定顺序返回文档;
- 限制返回的文档数;
- 大型数据集分页;
- 减少返回的文档包含的字段;
- 查找数据集中特定字段的不同值。
- 根据字段值将文档分组;
- 创建聚合流水线(aggregation pipeline);
- 使用聚合流水线来操作结果;
- 创建包含reduce和finalize函数的映射-归并(map reduce)操作;
- 使用映射-归并将一组文档归并为特定形式。
理解Cursor对象
在MongoDB shell中对Collection对象执行有些操作时,结果是以Cursor对象的方式返回的。Cursor对象相当于一个指针,可通过迭代它来访问数据库中的一组对象。例如,当您使用find()时,返回的并非实际文档,而是一个Cursor对象,您可以使用它来读取结果中的文档。
由于Cursor对象是可以迭代的,因此在内部存储了一个指向当前位置的索引,这让您能够每次读取一个文档。别忘了,有些操作只影响Cursor中的当前文档,并将索引加1;而有些操作影响当前索引之后的所有文档。 列出了可调用Cursor对象的基本方法。这些方法让您能够操作Cursor对象,并控制对其表示的实际对象的访问。
- batchSize(size) 指定MongoDB在每个网络响应中向客户端返回的文档数,默认为20
- count() 返回Cursor对象表示的文档数
- explain() 返回一个文档,它描述了将用来返回查询结果的查询执行计划,包括要使用的索引。这提供了一种排除缓慢查询故障或优化请求的极佳方式
- forEach(function) 迭代Cursor对象中的每个文档,并对其执行指定的JavaScript函数。指定的JavaScript函数必须将文档作为唯一的参数。下面是一个示例: myColl.find().forEach(function(doc){ print(“name: “ + doc.name); });
- hasNext() 在使用next()迭代游标时使用。如果游标中还有其他文档,可以继续迭代,则返回true
- hint(index) 强制MongoDB使用一个或多个特定的索引进行查询。index可以是字符串,如hint(“myIndex_1”);也可以是文档,其中的属性为索引名,而值为1,如hint({ myIndex: 1})
- limit(maxItems) 将游标的结果集限制为maxItems指定的大小
- map(function) 迭代Cursor中的每个文档,并对其执行指定的函数。将每次迭代的返回值都加入到一个数组中,并返回这个数组。例如: names = myColl.find().map(function(doc){ return doc.name; });
- max(indexBounds) 指定Cursor返回的文档中字段的最大值,例如: max({ height: 60, age: 10 })
- min() 指定Cursor返回的文档中字段的最小值,例如: min({ height: 60, age: 10 })
- next() 从Cursor返回下一个文档,并将迭代索引加1
- objsLeftInBatch() 指出Cursor返回的当前那批文档中还余下多少个。迭代到最前那批文档中最后一个后,需要再次向服务器发出请求以取回下批文档
- readPref(mode, tagSet) 指定Cursor的读取首选项,以控制客户端向副本集发送查询的方式
- size() 在执行方法skip()和limit()后,返回Cursor中的文档数
- skip(n) 返回另一个Cursor,它从n个文档后开始返回结果
- snapshot() 强制Cursor使用根据_id字段创建的索引,确保Cursor只返回每个文档一次
- sort(sortObj) 将结果按sortObj指定的方式排序。sortObj应包含用于排序的字段,并使用-1指定降序或使用1指定升序,例如: sort({ name: 1, age: -1 })
- toArray() 返回一个JavaScript对象数组,表示Cursor返回的所有文档。
理解查询运算符
在使用Collection对象查找和修改文档的操作中,有些操作允许您指定query参数。query参数对Cursor对象中返回的文档进行限制,使其值包含满足指定条件的文档。 query参数是标准的JavaScript对象,但使用了MongoDB shell和服务器都能明白的特殊属性名。query参数的属性称为运算符,因为它们对数据进行运算,以确定文档是否应包含在结果集中。这些运算符判断文档中字段的值是否符合指定条件。 例如,要查找所有字段count大于10且字段name为test的文档,可使用这样的query对象:
{count:{$gt:10}, name:'test'}
运算符$gt指定字段count大于10的文档。name:’test’使用了标准冒号语法,它指定字段name必须为test。注意到上述query对象包含多个运算符。在同一个查询中,可包含多个不同的运算符。 在query对象中指定字段时,可使用句点表示法来指定子文档的字段。例如,如果用户文档的格式如下:
{
name:"test",
stats: { height:74, eyes:'blue'}
}
则可使用下面的query对象来查询眼睛为蓝色的用户:
{stats.eyes:'blue'}
一些较常用的查询运算符。 决定返回的结果集的查询运算符
- field:value 与字段值为value的文档匹配,例如: {name:”myName”}
- $gt 与字段值大于指定值的文档匹配,例如: {size:{$gt:5}}
- $gte 与字段值大于等于指定值的文档匹配,例如: {size:{$gte:5}}
- $in 与字段值包含在指定数组中的文档匹配,例如: {name:{$in:[‘item1’, ‘item2’] } }
- $lt 与字段值小于指定值的文档匹配,例如: {size:{$lt:5}}
- $lte 与字段值小于等于指定值的文档匹配,例如: {size:{$lte:5}}
- $ne 与字段值不等于指定值的文档匹配,例如: {name:{$ne:”badName”}}
- $nin 与字段值不包含在指定数组中的文档匹配,例如: {name:{$in:[‘item1’, ‘item2’] } }
- $or 使用逻辑或连接查询子句,并返回符合任何一个子句条件的文档,例如: {$or:[{size:{$lt:5}},{size:{$gt:10} } ] }
- $and 使用逻辑与连接查询子句,并返回与两个子句条件都匹配的文档,例如: {$and:[{size:{$lt:5}},{size:{$gt:10} } ] }
- $not 反转查询表达式的效果,返回与查询表达式不匹配的文档,例如: {$not:{size:{$lt:5} } } }
- $nor 使用逻辑或非连接查询子句,返回与两个子句都不匹配的文档,例如: {$nor:{size:{$lt:5}},{name:”myName”} } }
- $exists 匹配包含指定字段的文档,例如: {specialField:{$exists:true}}
- $type 匹配指定字段为指定BSON类型(第1章的表1.1列出了BSON类型的编号)的文档,例如: {specialField:{$type:
} } - $mod 对执行字段执行求模运算,并返回结果为指定值的文档。求模运算条件是使用数组指定的,其中第一个数字为除数,第二个数组为余数。例如: {number:{$mod:[2,0] } }
- $regex 返回指定字段的值与指定正则表达式匹配的文档,例如: {myString:{$regex:’some.*exp’} }
- $all 返回这样的文档,即其指定数组字段包含所有指定的元素,例如: {myArr:{$all:[‘one’,’two’,’three] } }
- $elemMatch 返回这样的文档,即其指定的数组字段至少有一个元素与指定的条件都匹配,例如: {myArr:{$elemMatch:{value:{$gt:5},size:{$lt:3} } } }
- $size 返回这样的文档,即其指定的数组字段为指定的长度,例如:{myArr:{$size:5} }
从集合中获取文档
最常见的MongoDB数据库操作之一是检索一个或多个文档。例如,来看电子商务网站存储的商品信息,这些信息只存储一次,但被检索很多次。 数据检索好像很简单,但需要过滤、排序、显示和聚合结果时,可能变得非常复杂。 来看find()和findOne()的语法:
findOne(query, projection)
find(query, projection)
find()和findOne()的第一个参数都是一个query对象,该对象包含查询运算符,指定了文档的字段需要满足的条件。结果集只包含与查询条件匹配的文档。参数projection是一个这样的对象,即指定返回的文档应包含哪些字段。 方法find()和findOne()的差别在于,find()返回一个find()Cursor对象,表示与查询条件匹配的文档,而findOne返回与查询条件匹配的第一个文档。
查找特定的文档
知道如何使用方法find()和findOne()来访问集合中的多个文档后,您将发现自己想查找特定的文档。对结果集进行限制,使其只包含特定文档有多个优点,其中包括:
- 需要的网络流量更少;
- 客户端和服务器使用的内存更少;
- 客户端为查找重要数据需要做的处理更少。
- 要在方法find()限制返回的文档,可指定一个query对象,对Cursor中的返回文档进行限制。
根据特定的字段值查找文档
限制结果的最基本方式是,在查询文档中指定必须匹配的字段值,这样将只返回指定字段为指定值的文档。 例如,要获取数据库words中长度为5的单词,可使用类似于下面的查询:
find({size: 5});
同样,要从该数据库中获取单词there,可使用下面的查询:
find({word: "there"});
### 根据字段值数组查找文档 要查询特定字段为多个值之一的文档,可使用运算符$in。对于数据库words,一个这样的典型示例是,根据字段first查找以a、b或c打头的单词,如下所示:
find({first:{$in: ['a', 'b', 'c'] } });
根据字段值的大小查找文档
另一种常见的查询是,根据字段是否大于或小于指定的值来查询文档。运算符$gt和$lt让您能够指定一个字段和一个值,并在结果集中包含这样的文档,即其指定字段大于或小于指定的值。 下面的示例查找指定字段大于指定值的文档:
find({size:{$gt: 12}});
下面的示例查找指定字段小于指定值的文档:
find({size:{$lt: 12}});
根据数组字段的长度查找文档
另一种常见的查询是,查找指定数组字段为指定长度的文档,为此可使用运算符$size。 例如,下面的查询查找数组字段letters包含12个字母的单词:
find({letters:{$size: 12}});
同样,下面的查询查找数组字段letters长于10的单词:
find({letters:{$size: {$gt: 10}}});
根据子文档中的值查找文档
您可能还需要根据子文档包含的值来查询文档,为此只需使用句点语法来引用子文档的字段。例如,在数据库words中,可像下面这样指定子文档stats的字段vowels需满足的条件:
{"stats.vowels":{$gt:6}}
根据数组字段的内容查找文档
另一种很有用的查询是,根据数组字段的内容查找文档。运算符$all匹配这样的文档:其指定数组字段包含查询数组中所有的元素。 例如,下面的查询在数据库words中查找包含全部5个元音字母的单词:
{letters:{$all: ['a','e','i','o','u'] } }
根据字段是否存在查找文档
鉴于MongoDB不要求文档遵循结构化模式,因此可能出现这样的情况:某个字段在有些文档中有,而在其他文档中没有。在这种这种情况下,运算符$exists很有用,它让您能够对结果集进行限制,使其只包含有或者没有指定字段的文档。 例如,在数据库words中,不包含非字母字符的单词没有字段otherChars。下面的查询查找包含非字母字符的单词:
{otherChars: {$exists:true}}
根据子文档数组中的字段查找文档
在MongoDB文档模型中,一种比较棘手的查询是,根据数组字段中的子文档来查找文档。在这种情况下,文档包含一个子文档数组,而您要根据子文档中的字段来查询文档。 要根据数组字段中的子文档进行查询,可使用运算符$elemMatch。这个运算符让您能够根据数组中的子文档进行查询。 为演示运算符$elemMatch,最简单的方式是使用数据库words中的子文档数组字段charsets。字段charsets是一个文档数组,其结构如下:
{ type: <string>, chars: <array> }
下面的查询匹配这样的文档,即其字段charsets包含这样的文档:字段type为other,而数组字段chars的长度为2:
{charsets:{$elemMatch: {$and: [{type: 'other'},{chars: {$size: 2}}] } }}
计算文档数
访问MongoDB中的文档集时,您可能想在取回文档前获悉有多少个文档。在MongoDB服务器和客户端计算文档数的开销很小,因为不需要实际传输文档。 对find()返回的文档集执行操作时,也应明了将要处理的文档有多少,在大型环境中尤其如此。有时候,您只想知道文档数。例如,如果您要获悉应用程序中配置了多少用户,只需计算集合users中有多少个文档。 Cursor对象的方法count()指出它表示多少个文档。例如,下面的代码使用方法find()获取一个Cursor对象,再使用方法count()获取文档数:
cursor = wordsColl.find({first: {$in: ['a', 'b', 'c']}});
itemCount = cursor.count();
itemCount的值为与find()查询匹配的单词数。
对结果集进行排序
从MongoDB数据库检索文档时,一个重要方面是对找到的文档进行排序。在只想取回特定数量的文档(如前10个)或要对结果集进行分页时,这特别有用。Options对象提供了sort选项,让您能够指定用于排序的文档字段和方向。 Cursor对象的方法sort()让您能够指定要根据哪些字段对游标中的文档进行排序,并按相应的顺序返回文档。方法sort()将一个对象作为参数,这个对象将字段名用作属性名,并使用值1(升序)和-1(降序)来指定排序顺序。 例如,要按字段name降序排列,可使用下面的代码:
myCollection.find().sort({name:1}).sort({value:-1});
对于同一个游标,可多次使用sort(),从而依次按不同的字段进行排序。例如,要首先按字段name升序排列,再按字段value降序排列,可使用下面的代码:
myCollection.find().sort({name:1}).sort({value:-1});
限制结果集
在大型系统上查询较复杂的文档时,常常需要限制返回的内容,以降低对服务器和客户端网络和内存的影响。要限制与查询匹配的结果集,方法有三种:只接受一定数量的文档;限制返回的字段;对结果分页,批量地获取它们。
限制结果集的大小
要限制find()或其他查询请求返回的数据量,最简单的方法是对find()操作返回的Cursor对象调用方法limit(),它让Cursor对象返回指定数量的文档,可避免检索的对象量超过应用程序的处理能力。 例如,下面的代码只显示集合中的前10个文档,即便匹配的文档有数千个:
cursor = wordsColl.find();
cursor = cursor.limit(10);
cursor.forEach(function(word){
printjson(word);
});
限制返回的字段
为限制文档检索时返回的数据量,另一种极有效的方式是限制要返回的字段。文档可能有很多字段在有些情况下很有用,但在其他情况下没用。从MongoDB服务器检索文档时,需考虑应包含哪些字段,并只请求必要的字段。 要对find()操作从服务器返回的字段进行限制,可在find()操作中使用projection参数。projection参数是一个将字段名用作属性的JavaScript对象,让您能够包含或排除字段:将属性值设置为0/false表示排除;将属性值设置为1/true表示包含。然而,在同一个表达式中,不能同时指定包含和排除。 例如,返回first字段为t的文档时,要排除字段stats、value和comments,可使用下面的projection参数:
find({first:"t"}, {stats:false, value:false, comments:false});
仅包含所需的字段通常更容易。例如,如果只想返回first字段为t的文档的word和size字段,可使用下面的代码:
find({first:"t"}, {word:1, size:1 });
结果集分页
为减少返回的文档数,一种常见的方法是进行分页。要进行分页,需要指定要在结果集中跳过的文档数,还需限制返回的文档数。跳过的文档数将不断增加,每次的增量都是前一次返回的文档数。 要对一组文档进行分页,需要使用Cursor对象的方法limit()和skip()。方法skip()让您能够指定在返回文档前要跳过多少个文档。 每次获取下一组文档时,都增大方法skip()中指定的值,增量为前一次调用limit()时指定的值,这样就实现了数据集分页。 对大型数据集(尤其是从网站获得的数据集)进行分页时,需要使用find()操作为每一页创建一个游标。请不要为等待后续Web请求的到来而让游标长时间打开,这不是什么好主意,因为可能根本没有后续Web请求。 例如,下面的语句依次查找第1~10个文档、第11~20个文档和第21~30个文档:
cursor = collection.find().sort({name:1});
cursor.limit(10);
cursor.skip(0);
cursor = collection.find().sort({name:1});
cursor.limit(10);
cursor.skip(10);
cursor = collection.find().sort({name:1});
cursor.limit(10);
cursor.skip(20);
对数据进行分页时,务必调用方法sort()来确保数据的排列顺序不变。
查找不同的字段值
一种很有用的MongoDB集合查询是,获取一组文档中某个字段的不同值列表。不同(distinct)意味着纵然有数千个文档,您只想知道那些独一无二的值。 Collection对象的方法distinct()让您能够找出指定字段的不同值列表,这种方法的语法如下:
distinct(key, [query])
其中参数key是一个字符串,指定了要获取哪个字段的不同值。要获取子文档中字段的不同值,可使用句点语法,如stats.count。参数query是一个包含标准查询选项的对象,指定了要从哪些文档中获取不同的字段值。 例如,假设有一些包含字段first、last和age的用户文档,要获取年龄超过65岁的用户的不同姓,可使用下面的操作:
lastNames =myUsers.distinct('last', { age: { $gt: 65} } );
方法distinct()返回一个数组,其中包含指定字段的不同值,例如:
["Smith", "Jones", ...]
在MongoDB shell中对查找操作的结果进行分组
对大型数据集执行操作时,根据文档的一个或多个字段的值将结果分组通常很有用。这也可以在取回文档后使用代码来完成,但让MongoDB服务器在原本就要迭代文档的请求中这样做,效率要高得多。 要将查询结果分组,可使用Collection对象的方法group()。分组请求首先收集所有与查询匹配的文档,再对于指定键的每个不同值,都在数组中添加一个分组对象,对这些分组对象执行操作,并返回这个分组对象数组。方法group()的语法如下:
group({key, reduce, initial, [keyf], [cond], finalize})
下面描述了方法group()的参数。
- keys:一个指定要根据哪些键进行分组的对象,其属性为要用于分组的字段。例如,要根据文档的字段first和last进行分组,可使用{key: {first: 1, last: 1}}。
- cond:可选参数。这是一个query对象,决定了初始结果集将包含哪些文档。例如,要包含字段size的值大于5的文档,可使用{cond: {size: {$gt: 5}}。
- initial:一个包含初始字段和初始值的初始group对象,用于在分组期间聚合数据。对于每组不同的键值,都将创建一个初始对象。最常见的情况是,使用一个计数器来跟踪与键值匹配的文档数。例如:{initial: {“count”: 0}}。
- reduce:一个接受参数obj和prev的函数(function(obj, prev))。对于每个与查询匹配的文档,都执行这个函数。其中参数obj为当前文档,而prev是根据参数initial创建的对象。这让您能够根据obj来更新prev,如计数或累计。例如,要将计数递增,可使用{reduce: function(obj, prev) { prev.count++; }}。
- finalize:一个接受唯一参数obj的函数(function(obj)),这个参数是对与每个键值组合匹配的最后一个文档执行reduce函数得到的。对于每个键值组合,都将对其使用reduce函数得到的最终对象调用这个函数,然后以数组的方式返回结果。
- keyf:可选参数,用于替代参数key。可以不指定其属性为分组字段的对象,而指定一个函数,这个函数返回一个用于分组的key对象。这让您能够使用函数动态地指定要根据哪些键进行分组。
从MongoDB shell发出请求时使用聚合来操作数据 MongoDB的一大优点是,能够将数据库查询结果聚合成完全不同于原始集合的结构。MongoDB聚合框架相当杰出,简化了使用一系列操作来处理数据,以生成非凡结果的流程。
聚合指的是在MongoDB服务器中对文档执行一系列操作来生成结果集,其效率比在应用程序中检索并处理文档高得多,因为大量数据将由MongoDB服务器在本地处理。
接下来的几小节将介绍MongoDB聚合框架以及如何在MongoDB shell中使用它。
9.2.1 理解方法aggregate() Collection对象提供了对数据执行聚合操作的方法aggregate(),这个方法的语法如下:
aggregate(operator, [operator], […])
参数operator是一系列聚合运算符(如表9.1所示),让您能够指定要在流水线的各个阶段对数据执行哪种聚合操作。执行第一个运算符后,结果将传递给下一个运算符,后者对数据进行处理并将结果传递给下一个运算符,这个过程不断重复,直到到达流水线末尾。
在MongoDB 2.4和更早的版本中,方法aggregate()返回一个对象,该对象有一个名为result的属性,是一个包含聚合结果的迭代器。这意味着使用2.4版的MongoDB shell时,需要使用类似于下面的代码来访问聚合结果:
results = myCollection.aggregate( …); results.result.forEach( function(item){ … });
在更高的MongoDB版本中,方法aggregate()直接返回一个包含聚合结果的迭代器。这意味着使用2.6和更高版本的MongoDB shell时,需要使用类似于下面的代码来访问聚合结果:
results = myCollection.aggregate( …); results.forEach( function(item){ … });
程序清单9.3所示的示例针对的是MongoDB 2.4。
9.2.2 使用聚合框架运算符 MongoDB提供的聚合框架功能极其强大,让您能够反复将一个聚合运算符的结果传递给另一个运算符。为演示这一点,假设有下面的数据集:
{o_id:”A”, value:50, type:”X”} {o_id:”A”, value:75, type:”X”} {o_id:”B”, value:80, type:”X”} {o_id:”C”, value:45, type:”Y”}
下面的一系列聚合运算符将$match的结果交给运算符$group,再将分组集作为参数results传递给回调函数。注意到引用文档的字段值时,在字段名前加上了美元符号,如$o_id和$value。这种语法让聚合框架将其视为字段值而不是字符串。
aggregate( { $match:{type:”X”}}, { $group:{set_id:”$o_id”, total: {$sum: “$value”}}}, function(err, results){});
运算符$match执行完毕后,将交给$group进行处理的文档如下:
{o_id:”A”, value:50, type:”X”} {o_id:”A”, value:75, type:”X”} {o_id:”B”, value:80, type:”X”}
运算符$group执行完毕后,将把一个对象数组传递给回调函数,该数组中的对象包含字段set_id和total:
{set_id:”A”, total:”125”} {set_id:”B”, total:”80”}
表9.1列出了可在方法aggregate()的operator参数中指定的命令。
表9.1 可在方法aggregate()中使用的聚合运算符
运算符
描述
$project
通过重命名、添加或删除字段来重新定义文档。您还可以重新计算值以及添加子文档。例如,下面的示例包含字段title并排除字段name:{$project:{title:1, name:0}};下面的示例将字段name重命名为title:{$project:{title:”$name”}};下面的示例添加新字段total并根据字段price和tax计算其值:{$project:{total:{$add:[“$price”, “$tax”] } }
$match
使用本书前面讨论的查询运算符过滤文档集,如{$match:{value:{$gt:50}}}
$limit
限制传递给聚合流水线中下一个阶段的文档数,如{$limit:5}
$skip
指定执行聚合流水线的下一个阶段前跳过多少个文档,如{$skip:10}
$unwind
$unwind的值必须是数组字段的名称(必须在该数组字段名前加上$,这样它才会被视为字段名,而不是字符串)。$unwind对指定的数组进行分拆,为其中的每个值创建一个文档,如{$unwind:”$myArr”}
$group
将文档分组并生成一组新文档,供流水线的下一个阶段使用。在$group中必须定义新文档的字段;还可对各组的文档应用分组表达式运算符,如将value字段的值相加:{$group:{set_id:”$o_id”, total: {$sum: “$value”}}}
$sort
将文档交给聚合流水线的下一个阶段前,对它们进行排序。$sort指定包含属性field:
9.2.3 使用聚合表达式运算符 使用聚合运算符时,将创建新文档,这些文档将传递给聚合流水线的下一个阶段。MongoDB聚合框架提供了很多表达式运算符,可用于计算新字段的值以及对文档中的既有字段进行比较。
使用聚合运算符$group时,新文档定义的字段将对应于多个原始文档。MongoDB提供了一组运算符,可用于对原始文档的字段执行计算,以得到新文档的字段值。例如,设置新文档的字段maximumt,使其表示相应分组中原始文档的最大value字段值。表9.2列出了可在聚合运算符$group中使用的表达式运算符。
表9.2 可在聚合运算符$group中使用的表达式运算符
运算符
描述
$addToSet
返回一个数组,包含当前文档组中指定字段的不同值,如colors: {$addToSet: “$color”}
$first
返回当前文档组中第一个文档的指定字段的值,如firstValue:{$first: “$value”}
$last
返回当前文档组中最后一个文档的指定字段的值,如lastValue:{$last: “$value”}
$max
返回当前文档组中指定字段的最大值,如maxValue:{$max: “$value”}
$min
返回当前文档组中指定字段的最小值,如minValue:{$min: “$value”}
$avg
返回当前文档组中指定字段的平均值,如aveValue:{$avg: “$value”}
$push
返回一个数组,包含当前文档组中每个文档的指定字段值,如username:{$push: “$username”}
$sum
返回当前文档组中各个文档的指定字段值之和,如total:{$sum: “$value”}
计算新字段的值时,还可使用多个字符串运算符和算术运算符。表9.3列出了在聚合运算符中计算新字段的值时,较为常用的一些表达式运算符。
表9.3 在聚合表达式中使用的字符串运算符和算术运算符
运算符
描述
$add
将一系列数字相加,如valuePlus5:{$add:[“$value”, 5] }
$divide
接受两个数字,并将第一个数字与第二个数字相除,如valueDividedBy5:{$divide:[“$value”, 5] }
$mod
接受两个数字,并计算第一个数字除以第二个数字的余数,如valueMod5:{$mod:[“$value”, 5] }
$multiply
计算一系列数字的乘积,如valueTimes5:{$multiply:[“$value”, 5] }
$subtract
接受两个数字,并将第一个数字与第二个数字相减,如valueMinus5:{$subtract:[“$value”, 5] }
$concat
拼接多个字符串,如title:{$concat:[“$title”, “ “, “$name”] }
$strcasecmp
比较两个字符串,并返回一个指出比较结果的整数,如isTest:{$strcasecmp:[“$value”, “test”] }
$substr
返回字符串的指定部分,如hasTest:{$substr:[“$value”, “test”] }
$toLower
将字符串转换为小写,如titleLower:{$toLower:”$title”}
$toUpper
将字符串转换为大写,如titleUpper:{$toUpper:”$title”}
在MongoDB shell中使用映射-归并生成新的数据结果 MongoDB的一大优点是能够对数据查询结果进行映射-归并,生成与原始集合截然不同的结构。映射-归并指的是对数据库查询结果进行映射,再归并为截然不同的格式以方便使用。
通过使用映射-归并,可在MongoDB服务器上操作数据,再将结果返回给客户端,从而降低客户端的处理负担及需要返回的数据量。接下来的几小节介绍MongoDB映射-归并框架及其用法。
9.3.1 理解方法mapReduce() Collection对象提供了方法mapReduce(),可用于对数据执行映射-归并操作,再将结果返回给客户端。方法mapReduce()的语法如下:
mapReduce(map, reduce, arguments)
参数map是一个函数,将对数据集中的每个对象执行它来生成一个键和值,这些值被加入到与键相关联的数组中,供归并阶段使用。map函数的格式如下:
function(){