MongoDB学习笔记,基础+增删改查+索引+聚合...

mac2025-02-17  8

一 基础了解

对应关系 -> https://docs.mongodb.com/manual/reference/sql-comparison/ database -> database collection -> table document -> row //无模式 field -> column -------------------------------------------------------------------------------------- 使用数据库 use 数据库名称 创建数据库并创建集合myNewCollection1插入数据 use myNewDB db.myNewCollection1.insertOne( { x: 1 } ) -------------------------------------------------------------------------------------- 创建集合并插入数据 db.myNewCollection22.insertOne( { xxx: 1 } ) 固定大小集合 capped collection 先进先出 创建一个集合x1 是上限集合,大小200字节 最大2个document,先进先出 也可以不指定document大小db.createCollection("x1", { capped : true, size : 200} ) db.createCollection("x1", { capped : true, size : 200, max : 2 } ) 检查是否为上限集合 false true db.collection.isCapped() 返回集合有多少document db.collection.count() 转换为上限集合 db.runCommand({"convertToCapped": "collection", size: 100000}); 查看collection并升序转换成数组输出,降序 -1 printjson(db.collection.find().sort({$natural:1}).toArray()) collection methods -> https://docs.mongodb.com/manual/reference/method/js-collection/ -------------------------------------------------------------------------------------- BSON Types 插入数据为undefined db.collection.insert({x:undefined}) 查找需要 db.getCollection('a001').find({x:undefined})//错误 db.getCollection('a001').find({x:{$type:6}}) db.getCollection('a001').find({x:{$type:"undefined"}}) 详情:$type对应Number https://docs.mongodb.com/manual/reference/bson-types/ _id 5d89674154e8289fdac72ea5 十六进制 八位 5d896741 表示时间 十进制 1569285953 北京时间 2019/9/24 8:45:53 十位 54e8289fda 随机数 十进制 364672229338 六位 c72ea5 计数器从随机数开始 十进制 13053605 16 -> 10 进制 https://tool.lu/hexconvert/ 时间戳 -> 北京时间 https://tool.chinaz.com/Tools/unixtime.aspx

二 基本查询操作

写在一起中间无换行表示同一个效果

// db.people.insertOne( {//插入并创建表 // user_id: "abc123", // age: 55, // status: "A" // } ) // db.people.createIndex( { user_id: 1 } )//创建 增索引 // db.people.createIndex( { user_id: 1, age: -1 } )//创建 增索引 和 减索引 // db.people.drop()//删除表 // db.people.updateMany(//设置列 join_date 内容为当前时间,列没有就添加 // { }, // { $set: { join_date: new Date() } } // ) // db.people.updateMany(//删除所有列 join_date // { }, // { $unset: { "join_date": "" } } // ) // db.people.insertOne(//插入一条数据 // { user_id: "bcd001", age: 45, status: "A" } // ) // db.people.find()//查询所有数据 // db.people.find(//只查询三个字段 _id user_id status // { }, // { user_id: 1, status: 1 } // ) // db.people.find(//只查询两个字段 user_id status // { }, // { user_id: 1, status: 1, _id: 0 } // ) // db.people.find(//查询状态不等于A // { status: { $ne: "A" } } // ) // db.people.find(//查询status="A" AND age=50 // { status: "A", // age: 50 } // ) // db.people.find(//查询status="A" OR age=50 // { $or: [ { status: "A" } , { age: 50 } ] } // ) // db.people.find(// >25 // { age: { $gt: 25 } } // ) // db.people.find(// <25 // { age: { $lt: 25 } } // ) // db.people.find(// >25 <=50 // { age: { $gt: 25, $lte: 50 } } // ) // db.people.find( { user_id: /abc/ } )// LIKE '%abc%' // db.people.find( { user_id: { $regex: /abc/ } } ) // db.people.find( { user_id: /^abc/ } )// LIKE 'abc%' // db.people.find( { user_id: { $regex: /^abc/ } } ) // db.people.find( { status: "A" } ).sort( { user_id: 1 } )//ASC // db.people.find( { status: "A" } ).sort( { user_id: -1 } )//DESC // db.people.count()// count(*) // db.people.find().count() // db.people.count( { user_id: { $exists: true } } )// 含有user_id的所有count(*) // db.people.find( { user_id: { $exists: true } } ).count() // db.people.count( { age: { $gt: 500 } } )//age>500的count(*) // db.people.find( { age: { $gt: 500 } } ).count() // db.people.aggregate( [ { $group : { _id : "$status" } } ] )//安装status分组,查询别名_id 只查询status // db.people.distinct( "status" )//返回一个数组 ["A","B","C","CCCC"] // db.people.findOne()//查询第一条 // db.people.find().limit(1) // db.people.find().limit(5).skip(10)//查询大于第 11 12 13 14 15条,如果没有14 15 就显示 11 12 13 // db.people.updateMany(//更新年龄大于5555的状态设置为CCCC // { age: { $gt: 5555 } }, // { $set: { status: "CCCC" } } // ) // db.people.updateMany(//更新状态为CCCC的设置 // { status: "CCCC" } , // { $inc: { age: 3 } } // ) // db.people.deleteMany( { status: "D" } )//删除状态为D的所有数据 // db.people.deleteMany({})//清空表数据

三 查询

查询 比较查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-comparison/ $eq -> = -> { <field>: { $eq: <value> } } $ne -> != -> {field: {$ne: value} } $gt -> > -> { field: { $gt: value} } $gte -> >= -> { field: { $gte: value} } $lt -> < -> { field: { $lt: value} } $lte -> <= -> { field: { $lte: value} } 有一个就可以 $in -> in -> { field: { $in: [<value1>, <value2>, ... <valueN> ] } } 都没有才可以 $nin -> not in -> { field: { $nin: [ <value1>, <value2> ... <valueN> ]} } -------------------------------------------------------------------------------------- 逻辑查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-logical/ 第一个false 余下不执行 $and -> and -> { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] } $or -> or -> { $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] } 对or的结果取反 $nor -> not or -> { $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] } 对符合的结果取反 $not -> not -> { field: { $not: { <operator-expression> } } } -------------------------------------------------------------------------------------- 元素查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-element/ $exists -> exists -> { field: { $exists: true/false } } $type -> { field: { $type: [ <BSON type1> , <BSON type2>, ... ] } } // { field: { $type: "string" } } // { field: { $type: ["string","int"] } } -------------------------------------------------------------------------------------- 评估查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-evaluation/ // 根据表达式来匹配数据 $expr -> { $expr: { <expression> } } // 根据schema来匹配 required必须含有,properties属性,bsonType类型 $jsonSchema -> { $jsonSchema: <JSON Schema object> } 这里匹配 如果field=0,1,2,3,4,5 v1=2 v2=1 表示除2余1的数,所以是1 3 5 $mod -> { field: { $mod: [ v1, v2 ] } } 匹配正则表达式 {filed:{$regex:/a/}} -> 只要含有a,区分大小写 {filed:{$regex:/^a/}} -> 第一个字母是a,区分大小写 $regex -> 通常用 方式3 { <field>: { $regex: /pattern/, $options: '<options>' } }//方式1 { <field>: { $regex: 'pattern', $options: '<options>' } }//方式2 { <field>: { $regex: /pattern/<options> } }//方式3 全文检索,不支持中文,根据索引进行匹配, $text -> 例如 { $text: { $search: "coffee" } } 查找含有coffee的 非常强大 支持js $where 例如 db.x.find({ $where:function(){ return this.item=="ijk123"&&this.qty==3 //this表示document(行) } }) -------------------------------------------------------------------------------------- 数组查询操作符 -> https://docs.mongodb.com/manual/reference/operator/query-array/ 必须所有的值都要有,$in则表示只有一个就可以 $all -> { <field>: { $all: [ <value1> , <value2> ... ] } } 只要匹配一个满足就可以 $elemMatch -> { <field>: { $elemMatch: { <query1>, <query2>, ... } } } 例如: { results: { $elemMatch: { $gte: 80, $lt: 85 } } } { results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } } 根据数组大小匹配 $size -> 匹配数组大小为2的,两个效果相同 { field: { $size: 2 } } {$where:function(){return this.field.length==2}}

四 更新

更新 db.collection.update({},{$set:{"a":1}})更新第一条 db.collection.updateMany({},{$set:{"a":1}})更新全部 自动更新操作符 -> https://docs.mongodb.com/manual/reference/operator/update-field/ $inc -> { $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } } {},{$inc:{"age":1,"c":-2,"h.g":2}}//age+1 c-2 h.g+2 字段不存在会创建0+数值 $mul -> { $mul: { <field1>: <number1>, ... } } {},{$mul:{"age":5,"h":-1}}//age*5 h*(-1) 数值也可为小数,字段不存在会创建为0*数值 新值最小 就更新 $min -> { $min: { <field1>: <value1>, ... } } 新值最大 就更新 $max -> { $max: { <field1>: <value1>, ... } } $rename -> {$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } } {},{$rename:{"age":"age1","my.doc":"c.h"}}//更新字段 age -> age1 my.doc -> c.h $set -> { $set: { <field1>: <value1>, ... } } //如果不存在_id:1 不会做任何反应,如果存在,则会字段重新赋值,不存在的字段会添加 {_id:1},{$set:{"a":1,"h.g":2}} $unset -> { $unset: { <field1>: "", ... } } {},{$unset:{"a":""}}//字段a后面设置"" 这里就删除了字段a,不论a是什么类型 $setOnInsert -> db.collection.update( <query>, { $setOnInsert: { <field1>: <value1>, ... } }, { upsert: true } ) 例如: db.collection.update(//collection为空 会插入一个文档,并且设置一条 _id:1 c1:apple c2:100 { _id: 1 }, { $set: { c1: "apple" }, $setOnInsert: { c2: 100 } }, { upsert: true } ) $currentDate -> { $currentDate: { <field1>: <typeSpecification1>, ... } } 也可以把 date 换成 timestamp 字符戳 {},{$currentDate:{mydate:{$type:"date"}}}

五 数组

数组 $ -> { "<array>.$" : value } 可以作为占位符 表示一个 //_id=1 grades=80的把 grade.$ 改为999 只能改一条,改第一个 { _id: 1, grades: 80 }, { $set: { "grades.$" : 999 } } { "_id" : 1, "grades" : [ 85, 80, 80 ] } -> { "_id" : 1, "grades" : [ 85, 999, 80 ] } $[] -> { <update operator>: { "<array>.$[]" : value } } 可以做占位符 表示全部 {_id:1},{$inc:{"sz.$[]":3}} {_id:1,sz:[1,2,3]} -> {_id:1,sz:[4,5,6]} $[diy] -> 这里的diy可以随便改 就是一个标识符 {},{$set:{"sz.$[x]":777}},{arrayFilters:[{"$[x]":{$eq:3}}]} {"_id:1","sz":[3,5,3]} {"_id:2","sz":[3,3,8]} {"_id:1","sz":[777,5,777]}, {"_id:2","sz":[777,777,8]} $addToSet -> { $addToSet: { <field1>: <value1>, ... } } 将元素添加数组 {_id:1},{$addToSet:{"sz":"3"}} ->{"sz":["1","2"]} ->{"sz":["1","2","3"]} {_id:1},{$addToSet:{"sz":["4","5"]}} ->{"sz":["1","2"]} ->{"sz":["1","2",["4","5"]]} $pop -> { $pop: { <field>: <-1 | 1>, ... } } {_id:1},{$pop:{"sz":-1}}//移除数组第一个 {_id:1},{$pop:{"sz":1}}//移除数组最后一个 $pull -> { $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } } 字段后面跟条件 { _id: 1 }, { $pull: { scores: {$in:[0,5]} } }//自定义删除所有 0和5 { _id: 1 }, { $pull: { scores: {$gt:7} } }//删除大于7的 $pullAll -> { $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } } 删除数组所有的 0 和 5 { _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } } $push -> { $push: { <field1>: <value1>, ... } } {_id:1},{$push:{"sz":3}} -> {"sz":[1,2]} -> {"sz":[1,2,3]}//单个添加 {_id:1},{$push:{"sz":[4,5]}} -> {"sz":[1,2]} -> {"sz":[1,2,[4,5]]}//整体添加单个数组 {_id:1},{$push:{"sz":{$each:[4,5]}}} -> [1,2] -> [1,2,4,5]//批量添加 {_id:1},{$push:{"sz":{$each:[],$sort:1}}} -> [2,1,3] -> [1,2,3]//数组排序 1升序 -1降序 {_id:1},{$push:{"sz":{$each:[8,2],$sort:1}}} -> [2,1,3] -> [1,2,,2,3,8]//添加+排序 {_id:1},{$push:{"sz":{$each:[5,6],$sort:1,$slice:3}}} 原数据 -> 添加 -> 排序(1升序 -1降序) -> 截取(3前三条 -3后三条) [2,1,3] -> [2,1,3,5,6] ->[1,2,3,5,6] ->[1,2,3] $each { $addToSet: { <field>: { $each: [ <value1>, <value2> ... ] } } } { $push: { <field>: { $each: [ <value1>, <value2> ... ] } } } {_id:1},{$addToSet:{"sz":{$each:[4,5]}}}// [2,1] -> [2,1,4,5] {_id:1},{$push:{"sz":{$each:[4,5]}}}// [2,1] -> [2,1,4,5] $slice 截取 -> 配合$push $each一起使用 {_id:1},{$push:{"sz":{$each:[8,6],$slice:3}}} [1,2] -> [1,2,8]// 3前三条 -3后三条 0清空数组 $sort 排序 -> 配合$push $each一起使用 {_id:1},{$push:{"sz":{$each:[8,6],$sort:1}}} [1,2] -> [1,2,6,8]// 1升序 -1降序 $position 插入位置 -> 配合$push $each一起使用 {_id:1},{$push:{"sz":{$each:[9],$position:1}}} [3,5,8] -> [3,1,5,8] 1表示在第一个元素后面追加 0表示在开头添加 大于元素个数表示在最后追加

六 增删改查

增删改查 insert db.collection.insertOne({})//插入一条 db.collection.insertOne({})//插入第一条 db.collection.insertMany([{},{}])//插入多条 db.collection.insert({})//插入一条 db.collection.insert({},{})//插入第一条 db.collection.insert([{},{}])//插入多条 delete db.collection.deleteOne({"a":1})//删除a为1的第一条 db.collection.deleteMany({"a":1})//删除a为1的全部 db.collection.deleteMany({})//清空collection db.collection.remove() {"a":1}//删除a为1的全部 {"a":1},{justOne:true}//删除a为1的第一条 update db.collection.updateOne({"a":1},{$set:{"a":2}})//更新第一条 db.collection.updateOne({"a":1},{$set:{"a":2}})//更新全部 db.collection.replaceOne({"a":1},{"b":2,"c":3})//替换第一条的数据 find db.collection.findOne({"a":1})//查询符合条件的第一条数据 db.collection.find({})//查询collection全部数据 db.collection.findOneAndDelete({"a":1})//查询正常返回第一条并且删除 db.collection.findOneAndReplace({"a":1},{"c":2,"d":3})//查询正常返回第一条并且替换 //查询正常返回第一条并更新,字段不存在就添加 db.collection.findOneAndUpdate({"d":"dd"},{$set:{"e":"ee"}}) bulk 支持以下方法,一个出错,不影响其他的 insertOne updateOne updateMany replaceOne deleteOne deleteMany try { db.characters.bulkWrite( [ { insertOne : { "document" : { "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4 } } }, { insertOne : { "document" : { "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3 } } }, { updateOne : { "filter" : { "char" : "Eldon" }, "update" : { $set : { "status" : "Critical Injury" } } } }, { deleteOne : { "filter" : { "char" : "Brisbane"} } }, { replaceOne : { "filter" : { "char" : "Meldane" }, "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 } } } ] ); } catch (e) { print(e); }

七 索引创建

索引创建 Single Index 单键索引 db.collection.createIndex({"a":1})//a非数组 1升序索引 -1降序索引 Compound Index 复合索引 db.collection.createIndex( { "a": 1, "b": 1 } ) Multikey Index 多键值索引 db.collection.createIndex({"a":1})//这里的a是一个数组 db.collection.createIndex({"a":1,"b":1})//a数组 b非数组 创建复合索引 Text Indexes 全文索引,不支持中文 db.collection.createIndex( { "a": "text" } ) Hashed Indexes 哈希索引 db.collection.createIndex( { "_id": "hashed" } ) Unique Indexes 唯一索引 插入数据不可以重复 db.collection.createIndex( { "a": 1 }, { unique: true } ) Partial Indexes 局部索引 db.users.createIndex(//年龄>=21才能给username加升序索引,唯一索引 { username: 1 }, { unique: true, partialFilterExpression: { age: { $gte: 21 } } } ) Sparse Indexes 稀疏索引 db.collection.createIndex({"a":1},{sparse:true})//对a建立索引 TTL Indexes 过期索引*重要,可做定时过期 1,只支持单个索引,复合索引不支持 2,类型要为 BSON 日期 或 含有 BSON 日期的数组 3,expireAfterSeconds 单位秒,正的 或 0 ,如果为0 在指定日期时到期 4,如果是数组,最小的那个时间到期就会删除 5,不含有该索引字段 或 字段不是日期类型,不会过期 6,_id 不能设置 TTL索引 7,时间到期后不会立马删除,后台60s执行一次 只能设置一个字段,单位秒 db.collection.createIndex({"a":1},{expireAfterSeconds:65})

八 索引管理

索引管理 //插入自定义时间 db.test.insert({'time':ISODate("2012-11-02 07:58:51")}) 查看 表的全部索引 db.collection.getIndexes() 索引字段名 db.collection.getIndexKeys() 数据库全部索引 db.getCollectionNames().forEach(function(collection) { indexes = db[collection].getIndexes(); print("Indexes for " + collection + ":"); printjson(indexes); }); 删除 删除b升序索引 -1删除降序索引 db.collection.dropIndex({"b":1}) 删除全部索引 db.collection.dropIndexes() 修改 删除再创建

九 GridFS 分布式文件系统

GridFS 分布式文件系统 1,多机器储存备份 2,可以突破一般文件的限制,可以大于16M 3,分段存储,不是整个存储 mongofiles -> https://docs.mongodb.com/manual/reference/program/mongofiles/ 默认localhost:27017 --host 默认27017 --port 指定数据库 --db 前缀 默认fs --prefix .... ... ...

十 聚合管道

聚合管道 Aggregation Pipeline Stages -> https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/ db.collection.aggregate([{},{},...,{}])//一个{}表示一个管道 1,$addFields 2,$bucket 3,$bucketAuto 4,$collStats 5,$count aggregate([//查询字段score>80的总数,假设有3条记录 返回{"passing_scores":3} { $match: { score: {$gt: 80} } }, { $count: "passing_scores" } ]); 6,$facet 7,$geoNear 8,$graphLookup 9,$group { $group: { _id: null或者$字段 <field1>: { <accumulator1> : <expression1> }, ... } } $sum 相加 对字段price*quantity的结果相加得到总价格 totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } } $avg 平均值 邱quantity字段平均值 averageQuantity: { $avg: "$quantity" } $first 第一个值 $last 最后一个值 $min 最小值 $max 最大值 $push 对结果 对author分组,每个作者的标题String放入books数组 { $group : { _id : "$author", books: { $push: "$title" } } } aggregate( [//不分组 计算document数量 { $group: { _id: null, count: { $sum: 1 } } } ] ); { "_id" : null, "count" : 8 } --- aggregate( [ { $group : { _id : "$item" } } ] );//按照item字段分组 { "_id" : "abc" } { "_id" : "jkl" } { "_id" : "def" } { "_id" : "xyz" } --- aggregate( [ // First Stage { $group : { _id : "$item", totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } } } }, // Second Stage { $match: { "totalSaleAmount": { $gte: 100 } } } ] ) //先按照item分组,对字段price*quantity的结果相加得到总价格,如果总价格>=100就显示 --- $group : { _id : null, totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }, averageQuantity: { $avg: "$quantity" }, count: { $sum: 1 } } 计算所有行的总销售额,所有行的quantity平均值,所有行的数量 10,$indexStats 11,$limit aggregate(//取5条数据 { $limit : 5 } ); 12,$listSessions 13,$lookup 表关联 aggregate([ { $lookup: { from: "表2", localField: "表1字段", foreignField: "表2字段", as: "表1添加列名,类型数组,放匹配表2的document" } }, {$match:{"_id":1}}//对结果再进行匹配 _id:1 ]); // localField String -> foreignField String // localField String[] -> foreignField String 14,$match -> { $match: { <query> } } aggregate( [ { $match : { author : "dave" } } ] ); 15,$merge 16,$out aggregate([//把匹配到的结果放入diy的表中,如果已存在则自动清空内容再插入 { $match: {score: {$gt: 80}} }, { $out: "diy" } ]); 17,$planCacheStats 18,$project -> 要显示哪些字段 只显示_id title author字段 aggregate( [ { $project : { title : 1 , author : 1 } } ] ) 只显示title author字段 aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] ) 不显示lastModified字段 aggregate( [ { $project : { "lastModified": 0 } } ] ) 不显示author.first lastModified字段 aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] ) 不显示author字段中的first lastModified字段 aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] ) 显示title author.first author.last 并显示字段 author.middle,值不能为"" 或 不存在字段 aggregate( [ { $project: { title: 1, "author.first": 1, "author.last" : 1, "author.middle": { $cond: { if: { $eq: [ "", "$author.middle" ] }, then: "$$REMOVE", else: "$author.middle" } } } } ] ); aggregate( [ { $project: { "stop.title": 1 } } ] ) 等同于 aggregate( [ { $project: { stop: { title: 1 } } } ] ) aggregate( [ { $project: { title: 1, isbn: { prefix: { $substr: [ "$isbn", 0, 3 ] },//下标 0 1 2 group: { $substr: [ "$isbn", 3, 2 ] },//下标 3 4 publisher: { $substr: [ "$isbn", 5, 4 ] },//下标 5 6 7 8 title: { $substr: [ "$isbn", 9, 3 ] },//下标 9 10 11 checkDigit: { $substr: [ "$isbn", 12, 1] }//下标 12 }, lastName: "$author.last",//添加新字段 copiesSold: "$copies"//添加新字段 } } ] ) 数组 例子 { "_id" : 1, "x" : 1, "y" : 1 } aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] ) ->{ "_id" : 1, "myArray" : [ 1, 1 ] } 原字段中无someField,显示null aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] ) -> { "_id" : 1, "myArray" : [ 1, 1, null ] } 19,$redact 20,$replaceRoot 21,$replaceWith 22,$sample 23,$set 24,$skip -> { $skip: <positive integer> } aggregate(// 不显示前面5条记录 { $skip : 5 } ); 25,$sort ->{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } } aggregate([// 1升序 -1降序 { $sort : { age : 1, posts: -1 } } ]) 26,$sortByCount 27,$unset 28,$unwind

十一 mapReduce

mapReduce 重量级聚合 -> mapReduce -> map -> reduce -> finalize -> out 流程图解 -> https://docs.mongodb.com/manual/core/map-reduce/ 使用方法 -> https://docs.mongodb.com/manual/reference/command/mapReduce/ db.runCommand({ mapReduce: <collection>, map: <function>, reduce: <function>, finalize: <function>, out: <output>, query: <document>, sort: <document>, limit: <number>, scope: <document>, jsMode: <boolean>, verbose: <boolean>, bypassDocumentValidation: <boolean>, collation: <document>, writeConcern: <document> }); 方法介绍 -> https://docs.mongodb.com/manual/reference/method/db.collection.mapReduce/ db.collection.mapReduce( <map>, <reduce>, { out: <collection>, query: <document>, sort: <document>, limit: <number>, finalize: <function>, scope: <document>, jsMode: <boolean>, verbose: <boolean>, bypassDocumentValidation: <boolean> } ) 常用四项: 1,map function(){ emit(this.cust_id, this.price); } 发射出去 key-value , 这里 this就是当前的document 2,reduce function(key, values) { return result;//result类型与map类型一致 } 3,query { age:{ $gte: 18 }} 4,finalize 在reduce后执行 function(key, reducedValue) { return modifiedObject; } 例1:------------------------------------ db.a.insert([ {_id:1,sku_id:1,stock:1}, {_id:2,sku_id:3,stock:2}, {_id:3,sku_id:2,stock:3}, {_id:4,sku_id:1,stock:4}, {_id:5,sku_id:2,stock:5}, ]) var diy_map=function(){ emit(this.sku_id,this.stock) } var diy_reduce=function(k,v){ return Array.sum(v) } db.runCommand({ mapReduce:"a",//对应的collection名称 map:diy_map, reduce:diy_reduce, out:{inline:1}//在内存中执行 }) 输出 --- /* 1 */ { "results" : [ { "_id" : 1.0, "value" : 5.0 }, { "_id" : 2.0, "value" : 8.0 }, { "_id" : 3.0, "value" : 2.0 } ], "timeMillis" : 23, "counts" : { "input" : 5, "emit" : 5, "reduce" : 2, "output" : 3 }, "ok" : 1.0 } --- 如果把 return Array.sum(v) 换成 return {"my_k":k,"my_v":v} 则输出 --- /* 1 */ { "results" : [ { "_id" : 1.0, "value" : { "my_k" : 1.0, "my_v" : [ 1.0, 4.0 ] } }, { "_id" : 2.0, "value" : { "my_k" : 2.0, "my_v" : [ 3.0, 5.0 ] } }, { "_id" : 3.0, "value" : 2.0 } ], "timeMillis" : 24, "counts" : { "input" : 5, "emit" : 5, "reduce" : 2, "output" : 3 }, "ok" : 1.0 } --- 如果想把结果输出放入一个collection 把 out:{inline:1} 缓存 out:"diy_document" 输出 out:{inline:1}输出内容的"result":[{.},{.},{.}]换成 "result":"diy_document" --- /* 1 */ { "result" : "c", "timeMillis" : 40, "counts" : { "input" : 5, "emit" : 5, "reduce" : 2, "output" : 3 }, "ok" : 1.0 } --- diy_document内容为 out:{inline:1}输出result字段[]里的内容 --- /* 1 */ { "_id" : 1.0, "value" : { "my_k" : 1.0, "my_v" : [ 1.0, 4.0 ] } } /* 2 */ { "_id" : 2.0, "value" : { "my_k" : 2.0, "my_v" : [ 3.0, 5.0 ] } } /* 3 */ { "_id" : 3.0, "value" : 2.0 } --- 整合finalize var diy_map=function(){ emit(this.sku_id,this.stock) } var diy_reduce=function(k,v){ return {"my_k":k,"my_v":v}; } var diy_finalize=function(k,v){ v.diy_field="我是在diy_finalize添加的字段" return {"my_k2":k,"my_v2":v}; } db.runCommand({ mapReduce:"a",//对应的collection名称 map:diy_map, reduce:diy_reduce, finalize:diy_finalize, out:{inline:1}//在内存中执行 }) 输出 --- /* 1 */ { "results" : [ { "_id" : 1.0, "value" : { "my_k2" : 1.0, "my_v2" : { "my_k" : 1.0, "my_v" : [ 1.0, 4.0 ], "diy_field" : "我是在diy_finalize添加的字段" } } }, { "_id" : 2.0, "value" : { "my_k2" : 2.0, "my_v2" : { "my_k" : 2.0, "my_v" : [ 3.0, 5.0 ], "diy_field" : "我是在diy_finalize添加的字段" } } }, { "_id" : 3.0, "value" : { "my_k2" : 3.0, "my_v2" : 2.0 } } ], "timeMillis" : 33, "counts" : { "input" : 5, "emit" : 5, "reduce" : 2, "output" : 3 }, "ok" : 1.0 } ---
最新回复(0)