Fork me on GitHub

Mongodb学习笔记

 

一、CentOS安装mongodb

二、mongodb的三个元素

三、Bson Types

四、Sql与Mogondb对比

五、比较运算符

六、逻辑运算符

七、元素查询运算符

八、评估查询运算符

九、数组查询操作符

十、更新操作结构

十一、字段更新操作符

十二、数组更新

十三、位更新操作

十四、CURD 

十五、索引

十六、分布式文件系统GridFS

十七、重量级聚合框架

十八、轻量级聚合框架group

十九、distinct

二十、mapReduce

二十一、master-slave

二十二、ReplicaSet集群

二十三、mongodb分片(未完成)

二十四、驱动链接mongodb

 

一、CentOS安装mongodb

1,下载并安装mongodb

①下载地址:https://www.mongodb.com/download-center?jmp=nav#community

将下载的mongodb-linux-x86_64-3.6.2.tgz放置在centos的usr目录下

网盘下载:https://pan.baidu.com/s/1c4dcdig

②解压:mongodb-linux-x86_64-3.6.2.tgz

进入mongodb-linux-x86_64-3.6.2文件夹创建一个db文件夹

③启动mongodb

命令:bin/mongod --dbpath=db

默认端口号:27017

2,下载并安装robomongo可视化工具

①下载地址:https://robomongo.org/

网盘下载:https://pan.baidu.com/s/1oAl5kT0

 

3,连接mongodb服务器

mongodb客户端一直连接不上centos的mongodb服务器
启动mongodb服务须加上--bind_ip_all(例如:bin/mongod --dbpath=db --auth --bind_ip_all)

给mongodb服务器设置密码:
①./mongo 连接mongodb服务器(./mongo --port 27017 -u "userAdmin" -p "123" --authenticationDatabase "admin")
②use admin 切换至admin数据库
③db.createUser({user: "userAdmin",pwd: "123",roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]}) 创建管理员用户,并指定其权限

 

二、mongodb的三个元素

mongodb   对应   sqlserver

database=》database

collection=》table

document=》row

1,基本操作

①创建database

②创建collection

③创建document

1,capped collection(固定集合)

①可视化设置固定集合

两种存储引擎:wiredtiger,mmap

②代码创建固定集合

1)简单创建固定集合

db.createCollection("log", { capped : true, size : 5242880, max : 5000 } )

2)复杂创建固定集合

db.createCollection(<name>,
 { capped: <boolean>,
    autoIndexId: <boolean>,
    size: <number>,
    max: <number>,
    storageEngine: <document>,
    validator: <document>,
    validationLevel: <string>,
    validationAction: <string>,
    indexOptionDefaults: <document> 
} )

3)将集合转换为固定集合

db.runCommand({"convertToCapped": "mycoll", size: 100000});

4)查看collection的状态

db.log.stats()

5)倒序查询

db.log.find().sort( { $natural: -1 } )

 

三、Bson Types

参考文档:https://docs.mongodb.com/manual/reference/bson-types/

TypeNumberAliasNotes
Double 1 “double”  
String 2 “string”  
Object 3 “object”  
Array 4 “array”  
Binary data 5 “binData”  
Undefined 6 “undefined” Deprecated.
ObjectId 7 “objectId”  
Boolean 8 “bool”  
Date 9 “date”  
Null 10 “null”  
Regular Expression 11 “regex”  
DBPointer 12 “dbPointer” Deprecated.
JavaScript 13 “javascript”  
Symbol 14 “symbol” Deprecated.
JavaScript (with scope) 15 “javascriptWithScope”  
32-bit integer 16 “int”  
Timestamp 17 “timestamp”  
64-bit integer 18 “long”  
Decimal128 19 “decimal” New in version 3.4.
Min key -1 “minKey”  
Max key 127 “maxKey”  

1,通过find操作,用undefined做作为比较条件

printjson(db.mycollection.find({"name":{$type:6}}).toArray());
printjson(db.mycollection.find({"name":{$type:'undefined'}}).toArray());

2,Timestamps

var a = new Timestamp();
db.test.insertOne( { ts: a } );

 

四、Sql与Mogondb对比

1,创建和更改表

SQL Mongodb
CREATE TABLE people (
    id MEDIUMINT NOT NULL
        AUTO_INCREMENT,
    user_id Varchar(30),
    age Number,
    status char(1),
    PRIMARY KEY (id)
)
db.people.insertOne( {
    user_id: "abc123",
    age: 55,
    status: "A"
 } )
或者
db.createCollection("people")
ALTER TABLE people
ADD join_date DATETIME
 
db.people.updateMany(
    { },
    { $set: { join_date: new Date() } }
)
ALTER TABLE people
DROP COLUMN join_date
 
db.people.updateMany(
    { },
    { $unset: { "join_date": "" } }
)
CREATE INDEX idx_user_id_asc
ON people(user_id)
 db.people.createIndex( { user_id: 1 } )
CREATE INDEX
       idx_user_id_asc_age_desc
ON people(user_id, age DESC)
 db.people.createIndex( { user_id: 1, age: -1 } )
DROP TABLE people
 db.people.drop()

2,插入数据

SQL Mongodb
INSERT INTO people(user_id,
                  age,
                  status)
VALUES ("bcd001",
        45,
        "A")
db.people.insertOne(
   { user_id: "bcd001", age: 45, status: "A" }
)
 

3,查询数据

 

SQL Mongodb
SELECT *
FROM people
db.people.find()

 

SELECT id,
       user_id,
       status
FROM people
 
db.people.find(
    { },
    { user_id: 1, status: 1 }
)
SELECT user_id, status
FROM people
 
db.people.find(
    { },
    { user_id: 1, status: 1, _id: 0 }
)
SELECT *
FROM people
WHERE status = "A"
 
db.people.find(
    { status: "A" }
)
SELECT user_id, status
FROM people
WHERE status = "A"
 
db.people.find(
    { status: "A" },
    { user_id: 1, status: 1, _id: 0 }
)
SELECT *
FROM people
WHERE status != "A"
 
db.people.find(
    { status: { $ne: "A" } }
)
SELECT *
FROM people
WHERE status = "A"
AND age = 50
 
db.people.find(
    { status: "A",
      age: 50 }
)
SELECT *
FROM people
WHERE status = "A"
OR age = 50
 
db.people.find(
    { $or: [ { status: "A" } ,
             { age: 50 } ] }
)
SELECT *
FROM people
WHERE age > 25
 
db.people.find(
    { age: { $gt: 25 } }
)
SELECT *
FROM people
WHERE age < 25
 
db.people.find(
   { age: { $lt: 25 } }
)
SELECT *
FROM people
WHERE age > 25
AND   age <= 50
 
db.people.find(
   { age: { $gt: 25, $lte: 50 } }
)
SELECT *
FROM people
WHERE user_id like "%bc%"
 
db.people.find( { user_id: /bc/ } )
db.people.find( { user_id: { $regex: /bc/ } } )
SELECT *
FROM people
WHERE user_id like "bc%"
db.people.find( { user_id: /^bc/ } )
db.people.find( { user_id: { $regex: /^bc/ } } )
SELECT *
FROM people
WHERE status = "A"
ORDER BY user_id ASC
 db.people.find( { status: "A" } ).sort( { user_id: 1 } )
SELECT *
FROM people
WHERE status = "A"
ORDER BY user_id DESC
 db.people.find( { status: "A" } ).sort( { user_id: -1 } )
SELECT COUNT(*)
FROM people
 
db.people.count()
db.people.find().count()
SELECT COUNT(user_id)
FROM people
 
db.people.count( { user_id: { $exists: true } } )
db.people.find( { user_id: { $exists: true } } ).count()
SELECT COUNT(*)
FROM people
WHERE age > 30
 
db.people.count( { age: { $gt: 30 } } )
db.people.find( { age: { $gt: 30 } } ).count()
SELECT DISTINCT(status)
FROM people
 
db.people.aggregate( [ { $group : { _id : "$status" } } ] )
db.people.distinct( "status" )
SELECT *
FROM people
LIMIT 1
 
db.people.findOne()
db.people.find().limit(1)
SELECT *
FROM people
LIMIT 5
SKIP 10
 db.people.find().limit(5).skip(10)
EXPLAIN SELECT *
FROM people
WHERE status = "A"
 db.people.find( { status: "A" } ).explain()

4,修改数据

SQL Mongodb
UPDATE people
SET status = "C"
WHERE age > 25
db.people.updateMany(
   { age: { $gt: 25 } },
   { $set: { status: "C" } }
)
UPDATE people
SET age = age + 3
WHERE status = "A"
 
db.people.updateMany(
   { status: "A" } ,
   { $inc: { age: 3 } }
)

5,删除数据

SQL Mongodb
DELETE FROM people
WHERE status = "D"
db.people.deleteMany( { status: "D" } )
DELETE FROM people
 
db.people.deleteMany({})

 

五、比较运算符

比较运算符 备注 说明 用法
$eq = equal
{ <field>: { $eq: <value> } }
相当于field: <value> }
$gt > greater than {field: {$gt: value} }
$gte >= greater than equal {field: {$gte: value} }
$lt < less than
{field: {$lt: value} }
$lte <= less than equal field: $lte: value} }
$ne != not equal  {field: {$ne: value} }
$in in  
{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }
$nin !in not in field: $nin: <value1>, <value2> ... <valueN> ]} }

1,测试数据

db.inventory.insert([
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] },
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] },
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] },
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30, tags: [ "B", "A" ] },
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }])

2,案例

①查询qty>=20的数据

db.inventory.find({"qty":{$gte:20}})

②查询item对象中的name为ab的数据

db.inventory.find({"item.name":{$eq:"ab"}})
db.inventory.find({"item.name":"ab"})

③查询tags集合中包含C的数据

db.inventory.find({tags:{$in:["C"]}})

④查询出tags集合为[ [ "A", "B" ], "C" ]的数据

db.inventory.find({tags:{$eq:[["A","B"],"C"]}})

 

六、逻辑运算符

1,$and

①使用方法: { $and: [ { <expression1> }, { <expression2> } , ... , {<expressionN> } ] } 

②案例

db.inventory.find( { $and: [ { price: { $ne: 1.99 } }, { price: { $exists: true } } ] } )
db.inventory.find( {
    $and : [
        { $or : [ { price : 0.99 }, { price : 1.99 } ] },
        { $or : [ { sale : true }, { qty : { $lt : 20 } } ] }
    ]
} )

2,$not

①使用方法:  { field: { $not: { <operator-expression> } } } 

②案例

db.inventory.find( { price: { $not: { $gt: 1.99 } } } )
db.inventory.find( { item: { $not: /^p.*/ } } )

3,$nor(or的反向)

①使用方法: { $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] } 

②案例

db.inventory.find( { $nor: [ { price: 1.99 }, { sale: true } ]  } )
db.inventory.find( { $nor: [ { price: 1.99 }, { qty: { $lt: 20 } }, { sale: true } ] } )

4,$or

①使用方法: { $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] } 

②案例

db.inventory.find( { $or: [ { quantity: { $lt: 20 } }, { price: 10 } ] } )

 

七、元素查询运算符

1,$exists(判断存不存在字段)

①使用方法: { field: { $exists: <boolean> } } 

②案例

db.inventory.find( { qty: { $exists: true, $nin: [ 5, 15 ] } } )

2,$type

①使用方法: { field: { $type: <BSON type> } } 

②案例

db.addressBook.find( { "zipCode" : { $type : "number" } } )

 

八、评估查询运算符

1,$expr【允许在查询语言中使用聚合表达式。】

①使用方法: { $expr: { <expression> } } 

②案例

1)查询花费大于预算

{ "_id" : 1, "category" : "food", "budget": 400, "spent": 450 }
{ "_id" : 2, "category" : "drinks", "budget": 100, "spent": 150 }
{ "_id" : 3, "category" : "clothes", "budget": 100, "spent": 50 }
{ "_id" : 4, "category" : "misc", "budget": 500, "spent": 300 }
{ "_id" : 5, "category" : "travel", "budget": 200, "spent": 650 }
数据
db.monthlyBudget.find({$expr:{$gt:[ "$spent","$budget" ]}})

2)qty>=100的情况(price/2)<5;qty<100的情况(price/4)<5

{ "_id" : 1, "item" : "binder", "qty": 100 , "price": 12 }
{ "_id" : 2, "item" : "notebook", "qty": 200 , "price": 8 }
{ "_id" : 3, "item" : "pencil", "qty": 50 , "price": 6 }
{ "_id" : 4, "item" : "eraser", "qty": 150 , "price": 3 }
supplies数据
db.supplies.find( {
    $expr: {
       $lt:[ {
          $cond: {
             if: { $gte: ["$qty", 100] },
             then: { $divide: ["$price", 2] },
             else: { $divide: ["$price", 4] }
           }
       },
       5 ] }
} )

2,$jsonSchema【根据给定的JSON模式验证文档】

①使用方法: { $jsonSchema: <schema> } 

参照文档:https://docs.mongodb.com/manual/reference/operator/query/jsonSchema/#op._S_jsonSchema

3,$mod【取模运算】

①使用方法: { field: { $mod: [ 除数, 余] } } 

②案例

{ "_id" : 1, "item" : "abc123", "qty" : 0 }
{ "_id" : 2, "item" : "xyz123", "qty" : 5 }
{ "_id" : 3, "item" : "ijk123", "qty" : 12 }
inventory数据

捞出qty除4余0的数据

db.inventory.find( { qty: { $mod: [ 4, 0 ] } } )

3,$regex【选择值与指定正则表达式匹配的文档】

①使用方法: { <field>: /pattern/<options> } 

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }
Option描述语法限制
i 不区分大小写  
m

对于包含锚的模式(即起始为^,结束为$),在每行的开始或结束处匹配具有多行值的字符串。 没有这个选项,这些锚点匹配字符串的开头或结尾。 有关示例,请参阅多行匹配以指定模式开始的行。
如果模式不包含锚,或者字符串值没有换行符(例如\ n),则m选项不起作用。

 
x

忽略$regex模式中的所有空格字符,除非转义或包含在字符类中

需要使用$ options语法的$ regex
s 允许点字符匹配包括换行符的所有字符 需要使用$ options语法的$ regex

②案例

{ "_id" : 100, "sku" : "abc123", "description" : "Single line description." }
{ "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" }
{ "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before     line" }
{ "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }
products数据

查询sku789结尾的数据(忽略大小写)

db.products.find( { sku: { $regex: /789$/ } } )
db.products.find( { sku:/789$/i } )

4,$text【全文搜索。不支持中文】

①使用方法:

{
  $text:
    {
      $search: <string>,
      $language: <string>,
      $caseSensitive: <boolean>,
      $diacriticSensitive: <boolean>
    }
}

参考文档:https://docs.mongodb.com/manual/reference/operator/query/text/#op._S_text

5,$where【匹配满足JavaScript表达式的文档】

①案例

{
   _id: 12378,
   name: "Steve",
   username: "steveisawesome",
   first_login: "2017-01-01"
}
{
   _id: 2,
   name: "Anya",
   username: "anya",
   first_login: "2001-02-02"
}
users数据
db.foo.find( { $where: function() {
   return (hex_md5(this.name) == "9b53e667f30cd329dca1ec9e6a83e994")
} } );

 

九、数组查询操作符

1,$all【匹配包含查询中指定的所有元素的数组】

①使用方法: { <field>: { $all: [ <value1> , <value2> ... ] } } 

②案例

{
   _id: ObjectId("5234cc89687ea597eabee675"),
   code: "xyz",
   tags: [ "school", "book", "bag", "headphone", "appliance" ],
   qty: [
          { size: "S", num: 10, color: "blue" },
          { size: "M", num: 45, color: "blue" },
          { size: "L", num: 100, color: "green" }
        ]
}

{
   _id: ObjectId("5234cc8a687ea597eabee676"),
   code: "abc",
   tags: [ "appliance", "school", "book" ],
   qty: [
          { size: "6", num: 100, color: "green" },
          { size: "6", num: 50, color: "blue" },
          { size: "8", num: 100, color: "brown" }
        ]
}

{
   _id: ObjectId("5234ccb7687ea597eabee677"),
   code: "efg",
   tags: [ "school", "book" ],
   qty: [
          { size: "S", num: 10, color: "blue" },
          { size: "M", num: 100, color: "blue" },
          { size: "L", num: 100, color: "green" }
        ]
}

{
   _id: ObjectId("52350353b2eff1353b349de9"),
   code: "ijk",
   tags: [ "electronics", "school" ],
   qty: [
          { size: "M", num: 100, color: "green" }
        ]
}
inventory数据

集合中包含"appliance", "school", "book" 的文档

db.inventory.find( { tags: { $all: [ "appliance", "school", "book" ] } } )

 

2,$elemMatch【如果数组中的元素匹配所有指定的$ elemMatch条件,则选择文档】

①使用方法: { <field>: { $elemMatch: { <query1>, <query2>, ... } } } 

②案例

{ _id: 1, results: [ { product: "abc", score: 10 }, { product: "xyz", score: 5 } ] }
{ _id: 2, results: [ { product: "abc", score: 8 }, { product: "xyz", score: 7 } ] }
{ _id: 3, results: [ { product: "abc", score: 7 }, { product: "xyz", score: 8 } ] }
survey数据
db.survey.find(
   { results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } }
)

 

3,$size【如果数组字段是指定的大小,则选择文档。】

db.collection.find( { field: { $size: 2 } } );

 

十、更新操作结构

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)
ParameterTypeDescription
query document

更新筛选条件

update document 修改
upsert boolean 可选的。 如果设置为true,则在没有文档匹配查询条件时创建一个新文档。 默认值为false,当找不到匹配项时不插入新文档。
multi boolean 可选的。 如果设置为true,则更新符合查询条件的多个文档。 如果设置为false,则更新一个文档。 默认值是false。 有关其他信息,请参阅多参数。
writeConcern document

可选的。 表达写入关注的文档。 省略使用默认的写入问题

collation document

可选的。

指定用于操作的排序规则。

整理允许用户为字符串比较指定特定于语言的规则

排序选项具有以下语法:

collation: {
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}

指定排序规则时,语言环境字段是强制性的; 所有其他整理字段是可选的。 有关这些字段的说明,请参阅整理文档。

如果排序规则未指定,但该集合具有默认排序规则(请参阅db.createCollection()),则该操作使用为该集合指定的排序规则。

如果没有为集合或操作指定排序规则,则MongoDB使用先前版本中使用的简单二进制比较进行字符串比较。

您无法为操作指定多个归类。 例如,不能为每个字段指定不同的排序规则,或者如果使用排序来执行查找,则不能使用一个排序规则查找,另一个排序规则。

arrayFilters array

可选的。 一组过滤器文档,用于确定要修改阵列字段上的更新操作的数组元素。

在更新文档中,使用$ [<identifier>]过滤位置运算符来定义标识符,然后在阵列过滤器文档中引用该标识符。 如果标识符未包含在更新文档中,则不能拥有标识符的数组筛选器文档。

注意

<identifier>必须以小写字母开头,并且只包含字母数字字符。

您可以在更新文档中多次包含相同的标识符; 但是,对于更新文档中的每个不同标识符($ [identifier]),必须正好指定一个相应的数组过滤器文档。 也就是说,不能为同一个标识符指定多个数组过滤器文档。 例如,如果更新语句包含标识符x(可能多次),则不能为arrayFilters指定以下值:

[ { "x.a": { $gt: 85} }, { "x.b": { $gt: 80 } } ]

但是,您可以在单个数组过滤器文档中的相同标识符上指定复合条件,例如:

[ { $or: [ { "x.a": { $gt: 85} }, { "x.b": { $gt: 80 } } ] } ]
[ { $and: [ { "x.a": { $gt: 85} }, { "x.b": { $gt: 80 } } ] } ]

 

十一、字段更新操作符

1,$currentDate【将字段的值设置为当前日期,可以是日期或时间戳】

①使用方法: { $currentDate: { <field1>: <typeSpecification1>, ... } } 

②案例

{ _id: 1, status: "a", lastModified: ISODate("2013-10-02T01:11:18.965Z") }
users数据
db.users.update({_id:2},{$currentDate:{lastModified:{ $type: "date" }}})

 

 

2,$inc【按指定的量增加字段的值】

①使用方法: { $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } } 

②案例

{
  _id: 1,
  sku: "abc123",
  quantity: 10,
  metrics: {
    orders: 2,
    ratings: 3.5
  }
}
products数据
db.products.update(
   { sku: "abc123" },
   { $inc: { quantity: -2, "metrics.orders": 1 } }
)

 

3,$min【如果指定的值小于现有字段值,则只更新字段】

①使用方法: { $min: { <field1>: <value1>, ... } } 

②案例

{ _id: 1, highScore: 800, lowScore: 200 }
scores数据

比原有lowScore的值小则更新

db.scores.update( { _id: 1 }, { $min: { lowScore: 150 } } )

 

4,$max【如果指定的值大于现有字段值,则只更新字段】

①使用方法: { $max: { <field1>: <value1>, ... } } 

②案例

{ _id: 1, highScore: 800, lowScore: 200 }
scores数据

比原有highScore的值大则更新

db.scores.update( { _id: 1 }, { $max: { highScore: 950 } } )

 

5,$mul【将字段的值乘以指定的数量】

①使用方法: { $mul: { field: <number> } } 

②案例

{ _id: 1, item: "ABC", price: 10.99 }

price值乘1.25

db.products.update(
   { _id: 1 },
   { $mul: { price: 1.25 } }
)

 

6,$rename【重命名一个字段】

①使用方法: {$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } } 

②案例

db.students.updateMany( {}, { $rename: { "nmae": "name" } } )
db.students.update( { _id: 1 }, { $rename: { "name.first": "name.fname" } } )

 

7,$set【设置文档中字段的值】

①使用方法: { $set: { <field1>: <value1>, ... } } 

②案例

{
  _id: 100,
  sku: "abc123",
  quantity: 250,
  instock: true,
  reorder: false,
  details: { model: "14Q2", make: "xyz" },
  tags: [ "apparel", "clothing" ],
  ratings: [ { by: "ijk", rating: 4 } ]
}
数据
db.products.update(
   { _id: 100 },
   { $set:
      {
        quantity: 500,
        details: { model: "14Q3", make: "xyz" },
        tags: [ "coats", "outerwear", "clothing" ]
      }
   }
)
db.products.update(
   { _id: 100 },
   { $set: { "details.make": "zzz" } }
)
db.products.update(
   { _id: 100 },
   { $set:
      {
        "tags.1": "rain gear",
        "ratings.0.rating": 2
      }
   }
)

 

8,$setOnInsert【如果更新导致插入文档,则设置字段的值。 对修改现有文档的更新操作没有影响】

db.products.update(
  { _id: 1 },
  {
     $set: { item: "apple" },
     $setOnInsert: { defaultQty: 200 }
  },
  { upsert: true }
)

upsert: true表示没有数据则插入;false表示没有数据则什么也不做
$setOnInsert: { defaultQty: 200 }表示只有插入时才会将defaultQty设置为 200。更新操作不会设置此值

 

9,$unset【从文档中删除指定的字段】

①使用方法: { $unset: { <field1>: "", ... } } 

②案例

db.products.update(
  { _id: 2 },
  {$unset:{item:""}}
)

 

十二、数组更新

1,$ 【充当占位符来更新匹配查询条件的第一个元素】

①使用方法: { "<array>.$" : value } 

②案例

db.students.insert([
   { "_id" : 1, "grades" : [ 85, 80, 80 ] },
   { "_id" : 2, "grades" : [ 88, 90, 92 ] },
   { "_id" : 3, "grades" : [ 85, 100, 90 ] }
])
students数据

id为1的项,将第一个grades为80的项改为82

db.students.update(
   { _id: 1, grades: 80 },
   { $set: { "grades.$" : 82 } }
)

 

2,$[] 【充当占位符来更新数组中与查询条件匹配的所有元素】

①使用方法: { <update operator>: { "<array>.$[]" : value } } 

②案例

 id为1的项,将grades所有项改为80

db.students.update(
   { _id: 1, grades: 82 },
   { $set: { "grades.$[]" : 80 } }
)

 

3,$[<identifier>] 【充当占位符以更新与匹配查询条件的文档的arrayFilters条件匹配的所有元素】

①使用方法:

{ <update operator>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } } ] }

②案例

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 102 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
students数据
db.students.update(
   { },
   { $set: { "grades.$[element]" : 100 } },
   { multi: true,
     arrayFilters: [ { "element": { $gte: 100 } } ]
   }
)

 

4,$addToSet 【只有在数组中不存在元素的情况下,才能将元素添加到数组中】

①使用方法: { $addToSet: { <field1>: <value1>, ... } } 

②案例

{ _id: 1, letters: ["a", "b"] }
test数据
db.test.update({_id:1},{$addToSet:{"letters":"e"}})
db.test.update({_id:1},{$addToSet:{"letters": {$each: [ "camera", "electronics", "accessories" ]}}})

 

5,$pop 【删除数据中的最后一个或第一个】

①使用方法: { $pop: { <field>: <-1 | 1>, ... } } 

-1:弹出第一个;1:弹出最后一个

②案例

{
    "_id" : 1,
    "letters" : [ 
        "d", 
        "camera", 
        "electronics", 
        "accessories"
    ]
}
数据
db.test.update({_id:1},{$pop:{"letters":-1}})

 

6,$pull 【删除所有匹配指定查询的数组元素】

①使用方法: { $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } } 

②案例

{
   _id: 1,
   fruits: [ "apples", "pears", "oranges", "grapes", "bananas" ],
   vegetables: [ "carrots", "celery", "squash", "carrots" ]
}
{
   _id: 2,
   fruits: [ "plums", "kiwis", "oranges", "bananas", "apples" ],
   vegetables: [ "broccoli", "zucchini", "carrots", "onions" ]
}
stores数据
db.stores.update(
    { },
    { $pull: { fruits: { $in: [ "apples", "oranges" ] }, vegetables: "carrots" } },
    { multi: true }
)
{
   _id: 1,
   results: [
      { item: "A", score: 5 },
      { item: "B", score: 8, comment: "Strongly agree" }
   ]
}
{
   _id: 2,
   results: [
      { item: "C", score: 8, comment: "Strongly agree" },
      { item: "B", score: 4 }
   ]
}
survey数据
db.survey.update(
  { },
  { $pull: { results: { score: 8 , item: "B" } } },
  { multi: true }
)


7,$push 【将一个项添加到数组中】

①使用方法: { $push: { <field1>: <value1>, ... } } 

ModifierDescription
$each

将多个值附加到数组字段

$slice 限制数组元素的数量。 需要使用$ each修饰符。
$sort

排序 1:升序 -1:降序

$position

指定数组中插入新元素的位置。 需要使用$ each修饰符。 如果没有$ position修饰符,$ push会将元素附加到数组的末尾。

②案例

db.students.update(
   { _id: 1 },
   {
     $push: {
       quizzes: {
         $each: [ { id: 3, score: 8 }, { id: 4, score: 7 }, { id: 5, score: 6 } ],
         $sort: { score: 1 }
       }
     }
   }
)
db.students.update(
   { _id: 2 },
   { $push: { tests: { $each: [ 40, 60 ], $sort: 1 } } }
)
db.students.update(
   { _id: 6 },
   {
     $push: {
       quizzes: {
          $each: [ { wk: 5, score: 8 }, { wk: 6, score: 7 }, { wk: 7, score: 6 } ],
          $sort: { score: -1 },
          $slice: 2 //限制长度,多了会截取
       }
     }
   },
   {
       upsert:true}
)

 

8,$pullAll 【从数组中删除所有匹配的值】

①使用方法: { $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } } 

②案例

{ _id: 1, scores: [ 0, 2, 5, 5, 1, 0 ] }
survey数据
db.survey.update( { _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } } )

 

9,$each【修改$push和$addToSet操作符以追加多个项目进行数组更新】

①使用方法:

{ $addToSet: { <field>: { $each: [ <value1>, <value2> ... ] } } }
{ $push: { <field>: { $each: [ <value1>, <value2> ... ] } } }

②案例

db.students.update(
   { name: "joe" },
   { $push: { scores: { $each: [ 90, 92, 85 ] } } }
)
db.inventory.update(
   { _id: 2 },
   { $addToSet: { tags: { $each: [ "camera", "electronics", "accessories" ] } } }
 )

 

10,$position【修改$push操作符以指定数组中的位置以添加元素】

①使用方法:

{
  $push: {
    <field>: {
       $each: [ <value1>, <value2>, ... ],
       $position: <num>
    }
  }
}

②案例

{ "_id" : 1, "scores" : [ 100 ] }
students数据
db.students.update(
   { _id: 1 },
   {
     $push: {
        scores: {
           $each: [ 50, 60, 70 ],
           $position: 0
        }
     }
   }
)
{ "_id" : 1, "scores" : [  50,  60,  70,  100 ] }
显示结果

 

11,$slice【修改$push操作符以限制更新数组的大小】

①使用方法:

{
  $push: {
     <field>: {
       $each: [ <value1>, <value2>, ... ],
       $slice: <num>
     }
  }
}
ValueDescription
0 将数组更新为一个空数组([])
负数 保留数据最后一位,数组超出大小从左边开始截取
正数

保留第一位,数组超出大小从右边开始截取

②案例

1)将grades数组更新空数组

db.students.update(
   { _id: 1 },
   {
     $push: {
       grades: {
          $each: [ 1,2,4 ],
          $sort: { score: -1 },
          $slice: 0
       }
     }
   }
)

2)插入1,2,4 只会保留4

db.students.update(
   { _id: 1 },
   {
     $push: {
       grades: {
          $each: [ 1,2,4 ],
          $sort: { score: -1 },
          $slice: -1
       }
     }
   }
)

3)插入1,2,4 只会保留1

db.students.update(
   { _id: 1 },
   {
     $push: {
       grades: {
          $each: [ 1,2,4 ],
          $sort: { score: -1 },
          $slice:1
       }
     }
   }
)

 

12,$sort【修改$ push操作符以重新排列存储在数组中的文档】

①使用方法:

{
  $push: {
     <field>: {
       $each: [ <value1>, <value2>, ... ],
       $sort: <sort specification>
     }
  }
}

1指定为升序,-1指定为降序。

②案例

{
  "_id": 1,
  "quizzes": [
    { "id" : 1, "score" : 6 },
    { "id" : 2, "score" : 9 }
  ]
}
students数据
db.students.update(
   { _id: 1 },
   {
     $push: {
       quizzes: {
         $each: [ { id: 3, score: 8 }, { id: 4, score: 7 }, { id: 5, score: 6 } ],
         $sort: { score: 1 }
       }
     }
   }
)
{
  "_id" : 1,
  "quizzes" : [
     { "id" : 1, "score" : 6 },
     { "id" : 5, "score" : 6 },
     { "id" : 4, "score" : 7 },
     { "id" : 3, "score" : 8 },
     { "id" : 2, "score" : 9 }
  ]
}
结果
{ "_id" : 2, "tests" : [  89,  70,  89,  50 ] }
students数据
db.students.update(
   { _id: 2 },
   { $push: { tests: { $each: [ 40, 60 ], $sort: 1 } } }
)
{ "_id" : 2, "tests" : [  40,  50,  60,  70,  89,  89 ] }
结果
{ "_id" : 3, "tests" : [  89,  70,  100,  20 ] }
students数据
db.students.update(
   { _id: 3 },
   { $push: { tests: { $each: [ ], $sort: -1 } } }
)
{ "_id" : 3, "tests" : [ 100,  89,  70,  20 ] }
结果

 

十三、位更新操作

1,$bit【执行整数值的按位AND,OR和XOR更新。】

①使用方法: { $bit: { <field>: { <and|or|xor>: <int> } } } 

②案例

{ _id: 1, expdata: NumberInt(13) }

db.switches.update(
   { _id: 1 },
   { $bit: { expdata: { and: NumberInt(10) } } }
)

1101
1010
----
1000

{ "_id" : 1, "expdata" : 8 }
{ _id: 2, expdata: NumberLong(3) }

db.switches.update(
   { _id: 2 },
   { $bit: { expdata: { or: NumberInt(5) } } }
)

0011
0101
----
0111

{ "_id" : 2, "expdata" : NumberLong(7) }
{ _id: 3, expdata: NumberLong(1) }

db.switches.update(
   { _id: 3 },
   { $bit: { expdata: { xor: NumberInt(5) } } }
)

0001
0101
----
0100

{ "_id" : 3, "expdata" : NumberLong(4) }

 

十四、CURD 

1,Insert

1)db.collection.insertOne()【将单个文档插入到一个集合中】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne

db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

2)db.collection.insertMany()【将多个文档插入到一个集合中】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#db.collection.insertMany

db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)

3)db.collection.insert()【将单个文档或多个文档插入到集合中】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.insert/#db.collection.insert

db.collection.insert(
   <document or array of documents>,
   {
     writeConcern: <document>,
     ordered: <boolean>
   }
)

 

2,Query

1)查询嵌入式/嵌套文档

db.inventory.insertMany( [
   { item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
   { item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
   { item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
   { item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
   { item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
数据
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
db.inventory.find( { "size.uom": "in" } )
db.inventory.find( { "size.h": { $lt: 15 } } )
db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )

2)查询数组

db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
   { item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
   { item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
   { item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
   { item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }
]);
数据
db.inventory.find( { tags: ["red", "blank"] } )
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
db.inventory.find( { tags: "red" } )
db.inventory.find( { dim_cm: { $gt: 25 } } )
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
db.inventory.find( { "tags": { $size: 3 } } )

3)查询嵌入式文档数组

db.inventory.insertMany( [
   { item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
   { item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
   { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
   { item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
   { item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
数据
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
db.inventory.find( { 'instock.qty': { $lte: 20 } } )
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } ) 
db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
db.inventory.find( { "instock.qty": { $gt: 10,  $lte: 20 } } )
db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )

4)返回指定的字段

db.inventory.insertMany( [
  { item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
  { item: "notebook", status: "A",  size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
  { item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
  { item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
  { item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }
]);
数据
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
SELECT _id, item, status from inventory WHERE status = "A"
db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
SELECT item, status from inventory WHERE status = "A"

5)查询空字段或缺少字段

db.inventory.insertMany([
   { _id: 1, item: null },
   { _id: 2 }
])
数据
db.inventory.find( { item: null } )
db.inventory.find( { item : { $type: 10 } } )
db.inventory.find( { item : { $exists: false } } )

6)迭代游标

var myCursor = db.users.find( { type: 2 } );

while (myCursor.hasNext()) {
   print(tojson(myCursor.next()));
}
var myCursor = db.users.find( { type: 2 } );

while (myCursor.hasNext()) {
   printjson(myCursor.next());
}
var myCursor =  db.users.find( { type: 2 } );

myCursor.forEach(printjson);
var myCursor = db.inventory.find( { type: 2 } );
var documentArray = myCursor.toArray();
var myDocument = documentArray[3];
var myCursor = db.users.find( { type: 2 } );
var myDocument = myCursor[1];

 

3,Update

1)db.collection.updateOne() 【即使多个文档可能与指定的过滤器匹配,也会更新与指定过滤器匹配的单个文档】
详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.updateOne/#db.collection.updateOne

db.collection.updateOne(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

 

2)db.collection.updateMany() 【更新所有匹配指定过滤器的文档】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.updateMany/#db.collection.updateMany

db.collection.updateMany(
   <filter>,
   <update>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

 

3)db.collection.replaceOne() 【即使多个文档可能与指定的过滤器匹配,也只能替换与指定过滤器匹配的单个文档】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.replaceOne/#db.collection.replaceOne

db.collection.replaceOne(
   <filter>,
   <replacement>,
   {
     upsert: <boolean>,
     writeConcern: <document>,
     collation: <document>
   }
)

 

4)db.collection.update()

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.update/#db.collection.update

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

更新或替换与指定过滤器匹配的单个文档,或更新与指定过滤器匹配的所有文档。

默认情况下,db.collection.update()方法更新单个文档。 要更新多个文档,请使用multi选项。

 

4,Delete


1)db.collection.deleteOne() 【即使多个文档可能匹配指定的过滤器,也最多删除与指定过滤器匹配的单个文档】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.deleteOne/#db.collection.deleteOne

db.collection.deleteOne(
   <filter>,
   {
      writeConcern: <document>,
      collation: <document>
   }
)

 

2)db.collection.deleteMany() 【删除所有匹配指定过滤器的文档】

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.deleteMany/#db.collection.deleteMany

db.collection.deleteMany(
   <filter>,
   {
      writeConcern: <document>,
      collation: <document>
   }
)

 

3)db.collection.remove() 【删除单个文档或与指定过滤器匹配的所有文档】.

详细文档:https://docs.mongodb.com/manual/reference/method/db.collection.remove/#db.collection.remove

db.collection.remove(
   <query>,
   <justOne>
)

justOne(true:删除一个。false:删除多个)。默认为false

 

 

十五、索引

db.students.find({}).explain() //查询执行计划

1,Single Field Indexes(单键索引)

详细文档:https://docs.mongodb.com/manual/core/index-single/#create-an-index-on-an-embedded-field

1)在单个字段上创建升序索引

{
  "_id": ObjectId("570c04a4ad233577f97dc459"),
  "score": 1034,
  "location": { state: "NY", city: "New York" }
}
db.records.createIndex( { score: 1 } )

2)在嵌入式字段上创建索引

{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"score": 1034,
"location": { state: "NY", city: "New York" }
}
db.records.createIndex( { "location.state": 1 } )

3)在嵌入式文档上创建一个索引

{
"_id": ObjectId("570c04a4ad233577f97dc459"),
"score": 1034,
"location": { state: "NY", city: "New York" }
}
db.records.createIndex( { location: 1 } )

2,Compound Indexes(复合索引)

详细文档:https://docs.mongodb.com/manual/core/index-compound/

1)创建一个复合索引

{
"_id": ObjectId(...),
"item": "Banana",
"category": ["food", "produce", "grocery"],
"location": "4th Street Store",
"stock": 4,
"type": "cases"
}
db.products.createIndex( { "item": 1, "stock": 1 } )

3,Multikey Indexes(多键索引)

详细文档:https://docs.mongodb.com/manual/core/index-multikey/

要索引一个包含数组值的字段,MongoDB会为数组中的每个元素创建一个索引键

{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] }
{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] }
{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] }
{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] }
{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }

db.inventory.createIndex( { ratings: 1 } )

4,Hashed Indexes(hash索引)

详细文档:https://docs.mongodb.com/manual/core/index-hashed/

db.collection.createIndex( { _id: "hashed" } )

5,Partial Indexes(局部索引)

使用更小的空间提高部分性能

1)例如,以下操作将创建仅索引defaultQty字段大于200的文档的复合索引。

db.products.createIndex({defaultQty:1},{ partialFilterExpression: { defaultQty: { $gt: 200 } } })

6,Unique Indexes(唯一索引)

db.members.createIndex( { "user_id": 1 }, { unique: true } )

7,Sparse Indexes(稀疏索引)

详细文档:https://docs.mongodb.com/manual/core/index-sparse/

即使索引字段包含空值,稀疏索引也只包含具有索引字段的文档的条目。 索引跳过缺少索引字段的任何文档。 索引是“稀疏的”,因为它不包含集合的所有文档。 相比之下,非稀疏索引包含集合中的所有文档,为那些不包含索引字段的文档存储空值。

1)创建一个稀疏索引(使用a作为条件时会IXSCAN)

{ "_id" : ObjectId("523b6e32fb408eea0eec2647"), "a" : "a" }
{ "_id" : ObjectId("523b6e61fb408eea0eec2648"), "b" : "b" }
{ "_id" : ObjectId("523b6e6ffb408eea0eec2649"), "c" : "c"}

db.scores.createIndex( { a: 1 } , { sparse: true } )

2)只查询包含稀疏索引的字段(a)

db.getCollection('test').find().hint({ a: 1 })

结果:
/* 1 */
{
    "_id" : ObjectId("523b6e32fb408eea0eec2647"),
    "a" : "a"
}

 

8,TTL Indexes(过期索引)

详细文档:https://docs.mongodb.com/manual/core/index-ttl/

db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )
expireAfterSeconds:过期秒数
注:mongodb每60s执行一次task。所以把过期时间设置的过短,也会60s执行一次
db.dates.insert({
    lastdate:new Date(),
    a:"a"
    })

db.dates.createIndex({"lastdate":1},{expireAfterSeconds:1})

 

十六,分布式文件系统GridFS

1,何时使用GridFS?

在MongoDB中,使用GridFS存储大于16 MB的文件。 

2,GridFS集合

GridFS将文件存储在两个集合中:

  • chunks (fs.chunks)存储二进制块
  • files (fs.files)存储文件的元数据
{
  "_id" : <ObjectId>,  //chunk的唯一ObjectId。
  "files_id" : <ObjectId>, //文件集合中指定的“父”文档的_id。
  "n" : <num>, //chunk的序列号。 GridFS将所有chunk从0开始编号。
  "data" : <binary> //二进制
}
fs.chunks数据结构
{
  "_id" : <ObjectId>, //此文档的唯一标识符
  "length" : <num>, //文档的大小(以字节为单位)
  "chunkSize" : <num>, //每个块的大小(以字节为单位)默认大小是255千字节(kB)
  "uploadDate" : <timestamp>,//GridFS首次存储文档的日期
  "md5" : <hash>,//
  "filename" : <string>,//可选的。 GridFS文件的可读名称。
  "contentType" : <string>,//可选的。 GridFS文件的有效MIME类型。
  "aliases" : <string array>,//可选的。 一组别名字符串。
  "metadata" : <any>,//可选的。 元数据字段可以是任何数据类型,并且可以保存您想要存储的任何附加信息
}
fs.files数据结构

3,这个 fs.chunks的索引

GridFS使用files_id和n字段在块集合上使用唯一的复合索引。 这可以有效地检索块,如以下示例所示:

db.fs.chunks.find( { files_id: myFileID } ).sort( { n: 1 } )

如果此索引不存在,则可以发出以下操作以使用mongo shell创建它:

db.fs.chunks.createIndex( { files_id: 1, n: 1 }, { unique: true } );

4,这个 fs.files的索引

GridFS使用文件名和uploadDate字段在文件集合上使用索引。 这个索引允许高效地检索文件,如下例所示:

db.fs.files.find( { filename: myFileName } ).sort( { uploadDate: 1 } )

如果此索引不存在,则可以发出以下操作以使用mongo shell创建它:

db.fs.files.createIndex( { filename: 1, uploadDate: 1 } );

6,使用mongofiles命令行工具上传文件

详细文档:https://docs.mongodb.com/manual/reference/program/mongofiles/#bin.mongofiles

所有mongofiles命令都具有以下形式: mongofiles <options> <commands> <filename> 

mongofiles命令的组件是:

  1. Options. 您可以使用一个或多个这些选项来控制mongofiles的行为
  2. Commands. 使用这些命令之一来确定mongofiles的操作
  3. 一个文件名,它可以是:本地文件系统上的文件名称,也可以是GridFS对象.

1)案例

① 上传文件

[root@localhost bin]# ./mongofiles -d test put ./sp.3gp

②查看test数据库

 

 

十七、重量级聚合框架

参考文档:https://docs.mongodb.com/manual/reference/method/db.collection.aggregate/#db.collection.aggregate

注意:因为是管道执行,则需要注意执行顺序

1,使用方式: db.collection.aggregate(pipeline, options)¶ 

pipeline:管道

options:可选的。 aggregate()传递给聚合命令的其他选项。

管道:

NameDescription
$addFields 将新字段添加到文档。 输出包含输入文档和新添加字段中所有现有字段的文档。
$bucket 根据指定的表达式和存储区边界将传入文档分组到称为存储桶的组中。
$bucketAuto 根据指定的表达式将传入文档分类到特定数量的组(称为存储桶)。 桶边界自动确定,试图将文档均匀分布到指定数量的桶中。
$collStats 返回有关集合或视图的统计信息。
$count 返回聚合管道此阶段的文档数量。
$currentOp 返回有关MongoDB部署的活动和/或休眠操作的信息。 要运行,请使用db.aggregate()方法。
$facet 在同一组输入文档中的单个阶段内处理多个聚合流水线。 支持创建多方面的聚合,能够在单个阶段中跨多个维度或方面表征数据。
$geoNear 根据地理空间点的接近度返回有序的文档流。 包含地理空间数据的$ match,$ sort和$ limit功能。 输出文件包含一个额外的距离字段,并可包含位置标识符字段。
$graphLookup 对集合执行递归搜索。 为每个输出文档添加一个新的数组字段,其中包含该文档的递归搜索的遍历结果。
$group 分组计算
$indexStats 查询过程中的索引情况
$limit 返回制指定数量的文档
$listLocalSessions 列出当前连接的mongos或mongodinstance上最近使用的所有活动会话。 这些会话可能尚未传播到system.sessions集合。
$listSessions 列出所有活动时间足以传播到system.sessions集合的所有会话。
$lookup 表连接
$match 相当于我们的 where
$out 将最后的结果输出到指定的collection中去
$project 相当于我们sql操作的 select
$redact 根据存储在文档本身中的信息限制每个文档的内容,重新整形流中的每个文档。 包含$ project和$ match的功能。 可用于实施字段级别的编校。 对于每个输入文档,输出一个或零个文档。
$replaceRoot 用指定的嵌入式文档替换文档。 该操作将替换输入文档中的所有现有字段,包括_id字段。 指定嵌入在输入文档中的文档以将嵌入式文档提升到顶层。
$sample 从其输入中随机选择指定数量的文档。
$skip 跳过前n个文档
$sort 通过指定的排序键对文档流进行重新排序。 只有订单改变了; 文件保持不变。 对于每个输入文档,输出一个文档。
$sortByCount 根据指定表达式的值对传入文档分组,然后计算每个不同组中文档的数量。
$unwind 将数据拆解成每一个document

2,案例

①分组并计算amount的总和

{ _id: 1, cust_id: "abc1", ord_date: ISODate("2012-11-02T17:04:11.102Z"), status: "A", amount: 50 }
{ _id: 2, cust_id: "xyz1", ord_date: ISODate("2013-10-01T17:04:11.102Z"), status: "A", amount: 100 }
{ _id: 3, cust_id: "xyz1", ord_date: ISODate("2013-10-12T17:04:11.102Z"), status: "D", amount: 25 }
{ _id: 4, cust_id: "xyz1", ord_date: ISODate("2013-10-11T17:04:11.102Z"), status: "D", amount: 125 }
{ _id: 5, cust_id: "abc1", ord_date: ISODate("2013-11-12T17:04:11.102Z"), status: "A", amount: 25 }
orders 数据
db.orders.aggregate([
    {$match:{status:"A"}},
    {$group:{_id:"$cust_id",total:{$sum:"$amount"}}},
    {$sort:{total:-1}}
    ])

②返回①的执行计划

db.orders.aggregate([
    {$match:{status:"A"}},
    {$group:{_id:"$cust_id",total:{$sum:"$amount"}}},
    {$sort:{total:-1}}
    ],
    {
        explain:true
     }
     )

③分页

db.orders.aggregate([
    {$match:{status:"A"}},
    {$group:{_id:"$cust_id",total:{$sum:"$amount"}}},
    {$sort:{total:-1}},
    {$skip:1},//跳过一条
    {$limit:2}//返回两条数据
    ])
db.orders.find().skip(0).limit(10)//普通分页

③表连接

db.orders.insert([
   { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
   { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },
   { "_id" : 3  }
])
db.inventory.insert([
   { "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 },
   { "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 },
   { "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 },
   { "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 },
   { "_id" : 5, "sku": null, description: "Incomplete" },
   { "_id" : 6 }
])
数据
db.orders.aggregate([
    {
        $lookup:{
            from:"inventory",
            localField:"item",
            foreignField:"sku",
            as:"inventory_docs"
        }
    }
])

 

十八、轻量级聚合框架group

详细文档:https://docs.mongodb.com/manual/reference/command/group/

使用方法:

{
  group:
   {
     ns: <namespace>,
     key: <key>,
     $reduce: <reduce function>,
     $keyf: <key function>,
     cond: <query>,
     finalize: <finalize function>
   }
}

ns:collections 你group的集合。。。

key: 我们group的键值。。

$keyf: 采用函数的定义我们的key, 我们可以后更高的灵活性来定义(去string的最后一个字母,或者中间,或者最后)

$reduce: 刚好就是我们聚合进行中的每个操作。。。

$initial: 聚合的初始文档。。。

cond: ($match) where条件

finalize: 在某一个groupkey结束后插入点。。。。

1,案例:

{
    "_id" : 1,
    "sku" : "abc",
    "description" : "product 1",
    "instock" : 120
}
{
    "_id" : 2,
    "sku" : "def",
    "description" : "product 2",
    "instock" : 80
}
{
    "_id" : 3,
    "sku" : "ijk",
    "description" : "product 3",
    "instock" : 60
}
{
    "_id" : 4,
    "sku" : "jkl",
    "description" : "product 4",
    "instock" : 70
}
{
    "_id" : 5,
    "sku" : "abcedfe",
    "description" : "product 1",
    "instock" : 120
}

{
    "_id" : 6,
    "sku" : "def而微软为",
    "description" : "product 2",
    "instock" : 70
}
数据
db.runCommand(
   {
     group:
       {
         ns: 'test',
         key: { "description":1 },   //分组的key
         cond: { "_id":{$gt:1} },    //筛选条件
         $reduce: function ( curr, result ) {
            //curr:   当前当前得到的document
            //result: 第一次就是我们目前的initial,后续的话看你怎么对result进行操作
                   result.count++;
            return result.total+=curr.instock;
         },
         initial: {"total":0,"count":0 },  //初始化文档
         finalize:function(result){     //结束执行
            result.avg=result.total/result.count;
         }
       }
   }
)


db.runCommand(
   {
     group:
       {
         ns: 'test',
        //key: { "description":1 },   //分组的key
         $keyf:function(doc){
             return {"description":1}      //doc: 当前的文档
          },
         cond: { "_id":{$gt:1} },
         $reduce: function ( curr, result ) {
            //curr:   当前当前得到的document
            //result: 第一次就是我们目前的initial,后续的话看你怎么对result进行操作
                   result.count++;
            return result.total+=curr.instock;
         },
         initial: {"total":0,"count":0 },
         finalize:function(result){
            result.avg=result.total/result.count;
         }
       }
   }
)

 

十九、distinct

参考文档:https://docs.mongodb.com/manual/reference/command/distinct/

使用方法:

{
  distinct: "<collection>",
  key: "<field>",
  query: <query>,
  readConcern: <read concern document>,
  collation: <collation document>
}

案例: db.runCommand ( { distinct: "test", key: "description" } ) 

 

二十、mapReduce

参考文档:https://docs.mongodb.com/manual/reference/method/db.collection.mapReduce/index.html

使用方法:

db.collection.mapReduce(
                         <map>,
                         <reduce>,
                         {
                           out: <collection>,
                           query: <document>,
                           sort: <document>,
                           limit: <number>,
                           finalize: <function>,
                           scope: <document>,
                           jsMode: <boolean>,
                           verbose: <boolean>,
                           bypassDocumentValidation: <boolean>
                         }
                       )
ParameterTypeDescription
map function

一个JavaScript函数,该函数将一个值与一个键关联或“映射”,并发出键和值对。

reduce function

一个JavaScript函数,它“减少”到一个对象,所有的值都与一个特定的键相关联。

options document 其他参数选项
bypassDocumentValidation boolean

可选的。允许mapReduce在操作过程中绕过文档验证。这允许您插入不符合验证要求的文档。

 

FieldTypeDescription
out string or document

指定map-reduce操作结果的位置。您可以输出到一个集合,输出到一个具有动作的集合,或者内联(inline)输出。在对集合的主要成员执行map-reduce操作时,可以输出到集合;对于次要成员,您可能只使用内联(inline)输出。

query document 条件
sort document 排序
limit number 指定输入到map函数的最大文档数。
finalize function

可选的。遵循reduce方法并修改输出

scope document 指定在映射中可访问的全局变量,减少和确定函数。
jsMode boolean

指定是否将中间数据转换为BSON格式,以执行映射和reduce函数。
默认值为false。

If false:

  • 在内部,MongoDB将映射函数发出的JavaScript对象转换为BSON对象。当调用reduce函数时,这些BSON对象被转换回JavaScript对象。
  • map-reduce操作将中间的BSON对象放在临时的磁盘存储中。这允许map-reduce操作执行任意大的数据集。

If true:

  • 在内部,map函数中发出的JavaScript对象仍然是JavaScript对象。不需要将对象转换为reduce函数,这会导致更快的执行。
  • 您只能使用少于500,000个不同关键参数的jsMode来获得mapper的emit()函数。
verbose boolean

指定是否在结果信息中包含计时信息。将verbose设置为true,以包含计时信息。
默认值为false。

collation document

可选的。
指定用于操作的排序规则。
Collation允许用户为字符串比较指定特定于语言的规则,比如字母大小写和重音符号的规则。
collation选项有以下语法:

collation: {
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}

在指定排序时,locale字段是强制的;所有其他排序字段都是可选的。有关字段的描述,请参见Collation文档。

如果排序未指定,但是集合有默认的排序规则(请参阅db.createCollection()),该操作将使用指定的排序集。
如果没有为集合或操作指定排序,MongoDB将使用以前版本中用于字符串比较的简单二进制比较。
不能为操作指定多个排序。例如,您不能指定每个字段的不同排序,或者如果使用排序来执行查找,您不能使用一个排序来查找,而另一个排序。
新的3.4版本中。

 

二十一、master-slave

详细文档:https://docs.mongodb.com/manual/core/master-slave/

1,基础搭建

①复制mongod程序到27000文件夹

②创建配置文件(1.config)

③创建db存储文件夹

2,配置master config

port=27000
bind_ip=192.168.1.150
dbpath=./db
master=true

启动mongodb: ./mongod --config 1.config 

3,配置slave config

port=27001
bind_ip=192.168.1.150
dbpath=./db
slave=true
source=192.168.1.150:27000

启动mongodb: ./mongod --config 1.config 

4,其他配置项

only:可选的。 指定数据库的名称。 指定时,MongoDB将只复制指定的数据库。 

 

二十二、ReplicaSet集群

master挂掉其中一个secondary变为master

 

arbiter:仲裁者没有数据集的副本,也不能成为主数据集。 副本组可能会有仲裁者在选举主要增加一票。 仲裁者总是恰好1选投票,从而让副本集有奇数表决权的成员

1,配置

port=27000 
bind_ip=192.168.1.150
dbpath=./db
replSet=test

27001、27002、27003配置文件差不多

2,启动服务

./mongod --config 1.config

3,随便链接一台mongodb(例如链接192.168.1.150:27000)

添加集群

rs.initiate()//初始化ReplicaSet集群

rs.config()//查看配置信息

rs.status()//查看状态

//向集群中添加members
rs.add("192.168.1.150:27001")
rs.add("192.168.1.150:27002")

//添加仲裁
rs.addArb("192.168.1.150:27003")

 

二十三、mongodb分片(未完成)

1,配置

27000(mongos):

port=27000
bind_ip=192.168.1.150
configdb=192.168.1.150:27001

27001(config):

port=27001
bind_ip=192.168.1.150
dbpath=./db
configsvr=true

启动: ./mongod --config 1.config 

27002:

27003:

3,步骤

①开启config服务器

②开启mongos服务器

 

二十四、驱动链接mongodb

参考文档:http://mongodb.github.io/mongo-csharp-driver/2.2/getting_started/?jmp=docs&_ga=2.64367849.778289673.1521255001-1734184491.1516893909

nuget:MongoDB.Driver

    class Program
    {
        static void Main(string[] args)
        {
            // or use a connection string
            var client = new MongoClient("mongodb://192.168.1.150:27017");

            var db = client.GetDatabase("test");

            db.CreateCollection("aa");

        }
    }

 

posted on 2018-01-31 21:17  *Hunter  阅读(460)  评论(0编辑  收藏  举报

导航

AmazingCounters.com