|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: MongoDB最佳实践笔记 |
| 4 | +published: true |
| 5 | +categories: [MongoDB, Maizi] |
| 6 | +--- |
| 7 | + |
| 8 | +主要还得看官网 |
| 9 | + |
| 10 | +1. 安装命令 |
| 11 | +• sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 |
| 12 | +• echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list |
| 13 | +• sudo apt-get update |
| 14 | +• sudo apt-get install -y mongodb-org |
| 15 | + |
| 16 | +Try MongoDB: http://try.mongodb.org |
| 17 | + |
| 18 | + 停止服务: |
| 19 | + sudo service mongod stop |
| 20 | + 启动服务: |
| 21 | + sudo service mongod start |
| 22 | + 切换数据库 |
| 23 | + use 数据库名 |
| 24 | + |
| 25 | +2. 插入命令 |
| 26 | + |
| 27 | +插入数据到students collection |
| 28 | +db.students.insert({name: "张三", school: {name: "清华大学", city: "北京"}, age: 19, gpa: 3.97}) |
| 29 | + |
| 30 | +db.students.insert({name: "李四", school: {name: "北京大学", city: "北京"}, age: 20, gpa: 3.3}) |
| 31 | + |
| 32 | +db.students.insert({name: "王二", school: {name: "交通大学", city: "上海"}, age: 22, gpa: 3.68}) |
| 33 | + |
| 34 | +db.students.insert({name: "小牛", school: {name: "哈工大", city: "哈尔滨"}, age: 21, gpa: 3.50}) |
| 35 | + |
| 36 | +db.students.insert({name: "小马", school: {name: "交通大学", city: "西安"}, age: 21, gpa: 3.70}) |
| 37 | + |
| 38 | +db.students.insert({name: "小朱"}) |
| 39 | + |
| 40 | + |
| 41 | +3. 查询命令 |
| 42 | + |
| 43 | +值精确匹配的查询 |
| 44 | +db.students.find({name: "张三"}) |
| 45 | +两个条件(逻辑与) |
| 46 | +db.students.find({"school.name": "交通大学", "school.city": "西安"}) |
| 47 | +通过ID |
| 48 | +db.students.find({"_id" : ObjectId("542717c4a47ef7e2347ffbe0")}) |
| 49 | +逻辑或 |
| 50 | +db.students.find({$or: [{"school.name": "交通大学"}, {"school.city": "北京"}]}) |
| 51 | +逻辑与 |
| 52 | +db.students.find({$and: [{"school.name": "交通大学"}, {"school.city": "北京"}]}) |
| 53 | +大于小于等 |
| 54 | +db.students.find({age:{$lte:20}}) |
| 55 | +db.students.find({age:{$gte:20}}) |
| 56 | +db.students.find({age:{$lt:20}}) |
| 57 | +db.students.find({age:{$gt:20}}) |
| 58 | +db.students.find({age:{$ne:20}}) |
| 59 | + |
| 60 | +关于数据字段存在与否的查询 |
| 61 | +db.students.find({school:{$exists:false}}) |
| 62 | + |
| 63 | +基于正则表达式的逻辑查询 |
| 64 | +db.students.find({name: /^小/}) |
| 65 | +db.students.find({name: /.*四/}) |
| 66 | + |
| 67 | + |
| 68 | +3. Update命令 |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | +4. Bson Document |
| 73 | +Data Model设计参考资料 |
| 74 | +http://docs.mongodb.org/manual/data-modeling/ |
| 75 | + |
| 76 | + |
| 77 | +6. 内嵌数组查询 |
| 78 | +db.students.insert({name: "张三", school: {name: "清华大学", city: "北京"}, courses:[{name:"MongoDB", grade:88, quiz:[9,8,9,10]},{name:"Java", grade:99,quiz:[3,2,1,5]}], age: 19, gpa: 3.97}) |
| 79 | + |
| 80 | +db.students.insert({name: "李四", school: {name: "北京大学", city: "北京"}, courses:[{name:"MongoDB", grade:86, quiz:[5,4,3,7]},{name:"Java", grade:92}, {name:"C++", grade:65}], age: 20, gpa: 3.3}) |
| 81 | + |
| 82 | +db.students.insert({name: "王二", school: {name: "交通大学", city: "上海"}, age: 22, gpa: 3.68}) |
| 83 | + |
| 84 | +db.students.insert({name: "小牛", school: {name: "哈工大", city: "哈尔滨"}, courses:[{name:"Java", grade:81}, {name:"C++", grade:99}], age: 21, gpa: 3.50}) |
| 85 | + |
| 86 | +db.students.insert({name: "小马", school: {name: "交通大学", city: "西安"}, courses:[{name:"MongoDB", grade:96, quiz:[5,4,3,7]}], age: 21, gpa: 3.70}) |
| 87 | + |
| 88 | +db.students.insert({name: "小朱"}) |
| 89 | + |
| 90 | + |
| 91 | +7. 地理位置查询 |
| 92 | +db.pois.insert({name:"AAA Store", loc:{type:"Point", coordinates:[70,30]}}) |
| 93 | +db.pois.insert({name:"BBB Bank", loc:{type:"Point", coordinates:[69.99,30.01]}}) |
| 94 | +db.pois.insert({name:"CCC Park", loc:{type:"Polygon", coordinates:[[[70,30],[71,31],[71,30],[70,30]]]}}) |
| 95 | +db.pois.insert({name:"DDD Forest", loc:{type:"Polygon", coordinates:[[[65,68],[67,68],[67,69],[65,68]]]}}) |
| 96 | + |
| 97 | +附近地点查询 |
| 98 | +db.pois.find({loc:{ |
| 99 | + $near: { |
| 100 | + $geometry: { |
| 101 | + type: "Point" , |
| 102 | + coordinates: [ 70 , 30 ] |
| 103 | + }, |
| 104 | + $maxDistance: 1000000 |
| 105 | + } |
| 106 | +}}) |
| 107 | + |
| 108 | +区域内地点查询 |
| 109 | +db.pois.find({loc:{ |
| 110 | + $geoWithin:{ |
| 111 | + $geometry :{ |
| 112 | + type : "Polygon", |
| 113 | + coordinates : [[[70,30],[71,31],[71,30],[70,30]]] |
| 114 | + } |
| 115 | + } |
| 116 | +}}) |
| 117 | + |
| 118 | +使用geoNear command |
| 119 | +db.runCommand( |
| 120 | + { |
| 121 | + geoNear: "pois", |
| 122 | + near: { type: "Point", coordinates: [ 70, 30 ] }, |
| 123 | + spherical: true, |
| 124 | + minDistance: 3000, |
| 125 | + maxDistance: 7000 |
| 126 | + } |
| 127 | +) |
| 128 | + |
| 129 | +9. 全文搜索 |
| 130 | + |
| 131 | +db.text.insert({content:"text performs a text search on the content of the fields indexed with a text index."}) |
| 132 | +db.text.insert({content:"When dealing with a small number of documents, it is possible for the full-text-search engine to directly scan the contents of the documents with each query, a strategy called 'serial scanning.' This is what some rudimentary tools, such as grep, do when searching."}) |
| 133 | +db.text.insert({content:"Soros enjoys playing mongo."}) |
| 134 | +db.text.insert({content:"Why don't you use mongo-db?"}) |
| 135 | + |
| 136 | + |
| 137 | + |
| 138 | + |
| 139 | + |
| 140 | +10. 学生成绩Group命令 |
| 141 | +db.students.group({ |
| 142 | + key:{age:1}, |
| 143 | + cond: {age:{$exists:true}}, |
| 144 | + reduce:function(cur, result) { result.count += 1; result.total_gpa += cur.gpa; result.ava_gpa = result.total_gpa / result.count;}, |
| 145 | + initial: { count: 0 , total_gpa: 0} |
| 146 | + }) |
| 147 | + |
| 148 | +11. 数据聚合 -- 流水线 |
| 149 | +各年龄段平均GPA计算和排序 |
| 150 | + |
| 151 | +db.students.aggregate([ |
| 152 | + {$match:{age:{$exists:true}}}, |
| 153 | + {$group:{_id:"$age", count: {$sum:1}, total_gpa:{$sum:"$gpa"}}}, |
| 154 | + {$project: {_id:1, ava_gpa:{$divide: ["$total_gpa", "$count"]}}}, |
| 155 | + {$sort:{ava_gpa:1}} |
| 156 | + ]) |
| 157 | + |
| 158 | +选课数量统计 |
| 159 | +db.students.aggregate( |
| 160 | + [ |
| 161 | + {$match: {age:{$exists:true},courses:{$exists:true}}}, |
| 162 | + {$project: {age:1, courses_count:{$size:"$courses"}}}, |
| 163 | + {$group: {_id:"$age", acc:{$avg:"$courses_count"}}}, |
| 164 | + {$sort:{acc:-1}} |
| 165 | + ] |
| 166 | +) |
| 167 | + |
| 168 | +选课不同种类统计 |
| 169 | +db.students.aggregate( |
| 170 | + [ |
| 171 | + {$match: {age:{$exists:true},courses:{$exists:true}}}, |
| 172 | + {$project: {_id:-1, age:1, "courses.name":1}}, |
| 173 | + {$unwind:"$courses"}, |
| 174 | + {$group: {_id:"$age", courses:{$addToSet:"$courses.name"}}}, |
| 175 | + {$project: {_id:1, cc:{$size:"$courses"}}}, |
| 176 | + {$sort: {cc:-1}} |
| 177 | + ] |
| 178 | +) |
| 179 | + |
| 180 | + |
| 181 | +12 数据聚合MapReduce |
| 182 | + |
| 183 | +按age分组计算平均gpa (错误) |
| 184 | +db.students.mapReduce( |
| 185 | + function(){ |
| 186 | + emit(this.age, this.gpa); |
| 187 | + }, |
| 188 | + |
| 189 | + function(key, values){ |
| 190 | + return Array.sum(values)/values.length; |
| 191 | + }, |
| 192 | + |
| 193 | + { |
| 194 | + query : {age : {$exists : true}, gpa : {$exists : true}}, |
| 195 | + out : {inline:1} |
| 196 | + } |
| 197 | +) |
| 198 | + |
| 199 | +按age分组计算平均gpa (正确) |
| 200 | +db.students.mapReduce( |
| 201 | + function(){ |
| 202 | + emit(this.age, {gpa:this.gpa, count:1}); |
| 203 | + }, |
| 204 | + function(key, values){ |
| 205 | + reducedVal = { gpa: 0, count: 0 }; |
| 206 | + for (var i = 0; i < values.length; i++) { |
| 207 | + reducedVal.count += values[i].count; |
| 208 | + reducedVal.gpa += values[i].gpa; |
| 209 | + } |
| 210 | + return reducedVal; |
| 211 | + }, |
| 212 | + { |
| 213 | + query : {age : {$exists : true}, gpa : {$exists : true}}, |
| 214 | + out : {inline:1}, |
| 215 | + finalize:function(key, value){ |
| 216 | + value.avg = value.gpa / value.count; |
| 217 | + return value; |
| 218 | + } |
| 219 | + } |
| 220 | +) |
| 221 | + |
| 222 | +课程推荐 |
| 223 | +db.students.mapReduce( |
| 224 | + function(){ |
| 225 | + var course_names = this.courses.map( |
| 226 | + function(course){ |
| 227 | + return course.name |
| 228 | + }); |
| 229 | + var intersection_names = course_names.filter( |
| 230 | + function(c_name){ |
| 231 | + return params.indexOf(c_name) != -1 |
| 232 | + }); |
| 233 | + var diff_names = course_names.filter( |
| 234 | + function(c_name){ |
| 235 | + return params.indexOf(c_name) == -1 |
| 236 | + }); |
| 237 | + diff_names.forEach( |
| 238 | + function(c_name){ |
| 239 | + emit(c_name, intersection_names.length / course_names.length) |
| 240 | + }); |
| 241 | + }, |
| 242 | + function(key, values){ |
| 243 | + var total = values.reduce(function(p, c) { |
| 244 | + return p + c; |
| 245 | + }); |
| 246 | + |
| 247 | + return total; |
| 248 | + }, |
| 249 | + { |
| 250 | + query : {courses : {$exists : true}}, |
| 251 | + out : {inline:1}, |
| 252 | + scope: {params: ["MongoDB"]} |
| 253 | + } |
| 254 | +) |
| 255 | + |
| 256 | +推荐课程(使用Pipeline) |
| 257 | +db.students.aggregate([ |
| 258 | + {$project:{"c_names":{$map:{input: "$courses", as:"course", in:"$$course.name"}}}}, |
| 259 | + {$project:{c_names:1, |
| 260 | + intersection_names:{$setIntersection:[["MongoDB"], "$c_names"]}, |
| 261 | + diff_names:{$setDifference:["$c_names", ["MongoDB"]]} |
| 262 | + }}, |
| 263 | + {$unwind:"$diff_names"}, |
| 264 | + {$project:{diff_names:1, score: {$divide:[{$size: "$intersection_names"}, {$size:"$c_names"}]}}}, |
| 265 | + {$group: {_id:"$diff_names", score: {$sum: "$score"}}} |
| 266 | + |
| 267 | +]) |
| 268 | + |
| 269 | + |
0 commit comments