您的位置:首页 > 数据库 > Mongodb

mongodb入门

2017-04-15 18:22 351 查看
mongodb入门
学习mongodb

官方文档 https://docs.mongodb.com/v3.2/introduction/ 中文文档: http://www.runoob.com/mongodb/mongodb-sharding.html
(1)mongodb介绍

db.person.find({"id":8.0},{"name":1,"_id":0});

1. 文档数据库 mongodb
nosql => 图像数据库,kv数据库,文档数据库,列数据库(hbase),xml数据库。
文档数据库 最符合 关系数据库。

2. 便捷和丰富的查询手段。

3. 高可用: (主备) => 冗余。

4. 横向扩展。 分库分表(sharding)。=》(分片)

5. 支持多个存储引擎。 wiredtiger,mmap
mongodb提供了一个“存储引擎api”供第三方去扩展。。。

二:下载
1. 安装一下centos(6.5) + 虚拟机。。。

2. 下载mongodb版本:mongodb-linux-x86_64-3.2.8.tgz ,默认端口:27017
查看进程: netstat -anlp | grep 27017 --colour

3. mongodb有一个web端口:28017

三:下载mongodb gui 【sqlserve,mysql】 我们都应该有一个可视化工具。

robomongo, mongochef desktop style

php rockmongo

robomongo 和 navicat是一样。。。

四、安装
tar -zxvf mongodb-linux-x86_64-3.2.8.tgz
mv mongodb-linux-x86_64-3.2.8 mongodb
cd mongodb
mkdir db

启动mongodb
bin/mongod --dbpath=db

bin/mongod --dbpath=db &

可以看到日志在监听27017这个端口
2017-03-05T17:04:43.175+0800 I NETWORK [initandlisten] waiting for connections on port 27017

打开web 28017端口 执行命令 bin/mongod --dbpath=db --rest http://192.168.175.30:28017/
管理工具robomongo下载地址 https://robomongo.org/ 打开管理工具界面继续操作
create database trip
创建collection person
插入document
{
name:"jack",
age:20
}

(2)mongodb三大元素

一:database,collection,document
nosql是无模式的文档数据库。
mongodb sqlserver
database => database
collection => table
document => row

row: (每一行都是一样的字段,不可添加不可减少,也就说fields的个数在
定义table的时候就一定申明好了)

document: 它的每一个document都是独立的,同时也不是我们在createcollection
的时候申明好的。

例如下面2条记录
/* 1 */
{
"_id" : ObjectId("58bbdf1baadae81da73863fb"),
"name" : "jack",
"age" : 20
}

/* 2 */
{
"_id" : ObjectId("58bbe0a3aadae81da73863fc"),
"province" : "广东",
"city" : "湛江"
}

二:document

1. 有没有长度限制???

我们的document 和 json是非常相似的。。 16M (在很久以前是4M)。
mongodb 天生就是分布式,可扩展,高性能。。。 CAP
既然是分布式部署,存在两个问题: 内存【粒度太多】 和 网络带宽 【多而碎】
memcached 的value 是 1M
redis 的value 512M 【string】

2. 无模式的特点二

{name:"jack",name="jack"} 这个在普通的json是时做不了的。。。

二:百科全书上的介绍
文档: https://docs.mongodb.com/v3.2/core/databases-and-collections/
1. database
#使用数据库
use ctrip
#查找person所有记录
db.person.find()
#查找person age=20记录
db.person.find({age:20})

use myNewDB

db.myNewCollection1.insert( { x: 1 } )

测试
use ctrip
db.person.find()
db.person.insert({userid:"440823199086543315",name:"zhangsan"})
#创建plane collection
db.createCollection("plane")
db.getCollection("person").find()

2. 字段命名:java,C#,nodejs。。。。
不要使用“特殊字符”。
sql => mongodb 的对照

(3)mongodb固定集合

一: capped collection 【上限集合】
一个集合,它可以做到size的上限 和 document个数的上限。
bytes maxinum 指定collection的大小。
document maxinum 指定collection中的document的个数。。。
【日志,疲劳度过滤】
千人千面的crm系统。
【sms,edm的时候,三天内不要给这群人发送同样的信息】 find和insert操作
document为1w,这样我们就不需要自己去写代码删除。。。。。
mongodb wiredtiger,mmap。。
{_id:"guid", name:"jack",email:"3234234@qq.com"}

设置创建一张collection为 logs 设置document maxinum 为5
use ctrip
for(var i=1;i<100;i++){
db.logs.insert({"name":i})
}

db.logs.find()

var list =db.logs.find().toArray();
printjson(list);
最终结果为{95,96,97,98,99}
[
{
"_id" : ObjectId("58ccbf4ab42e045f99cc9a0d"),
"name" : 95
},
{
"_id" : ObjectId("58ccbf4ab42e045f99cc9a0e"),
"name" : 96
},
{
"_id" : ObjectId("58ccbf4ab42e045f99cc9a0f"),
"name" : 97
},
{
"_id" : ObjectId("58ccbf4ab42e045f99cc9a10"),
"name" : 98
},
{
"_id" : ObjectId("58ccbf4ab42e045f99cc9a11"),
"name" : 99
}
]

二:怎么通过代码去创建 capped collection
db.createCollection(<name>, { capped: <boolean>,
autoIndexId: <boolean>,
size: <number>,
max: <number>,
storageEngine: <document>,
validator: <document>,
validationLevel: <string>,
validationAction: <string>,
indexOptionDefaults: <document> } )

用shell创建capped collection
文档路径 https://docs.mongodb.com/v3.2/core/capped-collections/ db.createCollection("mylog", { capped : true, size : 5242880, max : 5000 } )

三:为了更好的去发现,我们还可以下载一下mongodb的源代码 【本身server,shell】的脚本。

四:如何倒序查询capped collection
var list=db.logs.find()toArray();
printjson(list);

#倒序查询
var list=db.logs.find().sort( { $natural: -1 } ).toArray();
printjson(list);

五:将一个普通集合 转换为 上限集合
db.runCommand({"convertToCapped": "mycoll", size: 100000});

六:ctrip hadoop方式来实现,2015年 30亿/日 存放7天

(4)mongodb的查询语句
一:mongodb的查询语句
sql 和 mongodb statement 有什么样的对照关系。。。
1. 术语对照
1. table joins $lookup
aggregation mapreduce,group,aggregation

MongoDB MySQL Oracle Informix DB2
Database Server mongod mysqld oracle IDS DB2 Server
Database Client mongo mysql sqlplus DB-Access DB2 Client

2. CURD的一些对照

《1》 表级别的一些修改操作

ALTER TABLE users
ADD join_date DATETIME

db.users.update(
{ },
{ $set: { join_date: new Date() } },
{ multi: true }
)

-----------------
select:

db.users.find(
{ $or: [ { status: "A" } ,
{ age: 50 } ] }
)
我们看到我们使用document的形式来展示operation操作。。

SELECT *
FROM users
WHERE user_id like "%bc%"

db.users.find( { user_id: /bc/ } )

find操作,接受两个document参数,返回cursor。。。

SELECT *
FROM users
LIMIT 1
db.users.findOne() or db.users.find().limit(1)

-------------- update ------------------

---------------- delete --------------------

参考网址:https://docs.mongodb.com/manual/reference/sql-comparison/
##############################################################################################
查看帮助:db.users.help()

sql与mongodb对应的语法关系 https://docs.mongodb.com/v3.2/reference/sql-comparison/ 1、建表
CREATE TABLE users (
id MEDIUMINT NOT NULL
AUTO_INCREMENT,
user_id Varchar(30),
age Number,
status char(1),
PRIMARY KEY (id)
)

db.users.insert( {
user_id: "abc123",
age: 55,
status: "A"
} )
或者:
db.createCollection("users")

2、更改表结构增加字段
ALTER TABLE users
ADD join_date DATETIME

看一下数据
/* 1 */
{
"_id" : ObjectId("58d62c60ba1f570392e137df"),
"user_id" : "abc123",
"age" : 55.0,
"status" : "A",
"join_date" : ISODate("2017-03-25T08:44:31.553Z")
}

删除字段
ALTER TABLE users
DROP COLUMN join_date

db.users.update(
{ },
{ $unset: { join_date: "" } },
{ multi: true }
)

3、创建索引
CREATE INDEX idx_user_id_asc
ON users(user_id)

db.users.createIndex( { user_id: 1 } )

CREATE INDEX
idx_user_id_asc_age_desc
ON users(user_id, age DESC)
db.users.createIndex( { user_id: 1, age: -1 } )

4、删除表
DROP TABLE users
db.users.drop()

5、插入
INSERT INTO users(user_id,
age,
status)
VALUES ("bcd001",
45,
"A")

db.users.insert(
{ user_id: "bcd001", age: 45, status: "A" }
)

6、查询###########################比较重要######################
SELECT *
FROM users

db.users.find()

SELECT id,
user_id,
status
FROM users
db.users.find(
{ },
{ user_id: 1, status: 1 }
)

SELECT user_id, status
FROM users
db.users.find(
{ },
{ user_id: 1, status: 1, _id: 0 }
)
SELECT *
FROM users
WHERE status = "A"
db.users.find(
{ status: "A" }
)
SELECT user_id, status
FROM users
WHERE status = "A"
db.users.find(
{ status: "A" },
{ user_id: 1, status: 1, _id: 0 }
)
SELECT *
FROM users
WHERE status != "A"
db.users.find(
{ status: { $ne: "A" } }
)
SELECT *
FROM users
WHERE status = "A"
AND age = 50
db.users.find(
{ status: "A",
age: 50 }
)
SELECT *
FROM users
WHERE status = "A"
OR age = 50
db.users.find(
{ $or: [ { status: "A" } ,
{ age: 50 } ] }
)
SELECT *
FROM users
WHERE age > 25
db.users.find(
{ age: { $gt: 25 } }
)
SELECT *
FROM users
WHERE age < 25
db.users.find(
{ age: { $lt: 25 } }
)
SELECT *
FROM users
WHERE age > 25
AND age <= 50
db.users.find(
{ age: { $gt: 25, $lte: 50 } }
)
SELECT *
FROM users
WHERE user_id like "%bc%"
db.users.find( { user_id: /bc/ } )
SELECT *
FROM users
WHERE user_id like "bc%"
db.users.find( { user_id: /^bc/ } )
SELECT *
FROM users
WHERE status = "A"
ORDER BY user_id ASC
db.users.find( { status: "A" } ).sort( { user_id: 1 } )
SELECT *
FROM users
WHERE status = "A"
ORDER BY user_id DESC
db.users.find( { status: "A" } ).sort( { user_id: -1 } )
SELECT COUNT(*)
FROM users
db.users.count()
or

db.users.find().count()
SELECT COUNT(user_id)
FROM users
db.users.count( { user_id: { $exists: true } } )
or

db.users.find( { user_id: { $exists: true } } ).count()
SELECT COUNT(*)
FROM users
WHERE age > 30
db.users.count( { age: { $gt: 30 } } )
or

db.users.find( { age: { $gt: 30 } } ).count()
SELECT DISTINCT(status)
FROM users
db.users.distinct( "status" )
SELECT *
FROM users
LIMIT 1
db.users.findOne()
or

db.users.find().limit(1)
SELECT *
FROM users
LIMIT 5
SKIP 10
db.users.find().limit(5).skip(10)
EXPLAIN SELECT *
FROM users
WHERE status = "A"
db.users.find( { status: "A" } ).explain()

性能分析如下:
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.users",
"indexFilterSet" : false,
"parsedQuery" : {
"status" : {
"$eq" : "A"
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"status" : {
"$eq" : "A"
}
},
"direction" : "forward"
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

7、更新

SQL Update Statements MongoDB update() Statements
UPDATE users
SET status = "C"
WHERE age > 25
db.users.update(
{ age: { $gt: 25 } },
{ $set: { status: "C" } },
{ multi: true }
)
UPDATE users
SET age = age + 3
WHERE status = "A"
db.users.update(
{ status: "A" } ,
{ $inc: { age: 3 } },
{ multi: true }
)

8、删除
DELETE FROM users
WHERE status = "D"
db.users.remove( { status: "D" } )
DELETE FROM users
db.users.remove({})

(5)比较运算符
官网地址为https://docs.mongodb.com/v3.2/reference/operator/query-comparison/
一:mongodb具体运算符。。。
在介绍CURD之前,我们一定要知道哪些原子性的运算符。。。
1.比较运算符。。。

$eq = "=" 等于
$gt (greater than ) >
$gte >= (equal)
$lt (less than) <
$lte <= (equal) 小于等于
$ne (not equal) != 不等于
$in in
$nin (not in) !in

测试数据:
{ _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. eq:

{ <field>: { $eq: <value> } }

<1> 简单类型
<2> 复杂类型(document,array)

document 是否等于 document => 逐字段比较 【C# 匿名类型】

//第一个:匹配简单类型(int,string);
db.inventory.find({"qty":15});
db.inventory.find( { qty: { $eq: 15 } } )

//第二个:匹配复杂类型
db.inventory.find({"item":{
"name" : "cd",
"code" : "123"
}});

//第三种:array的匹配

//db.inventory.find({"tags":{$eq:"A"}}) //forech查找

db.inventory.find({"tags":{$in:["A"]}}); //如果采用in的话,我们会更加的简洁。

3. $gt/$gte

{field: {$gt: value} }

db.inventory.find( { qty: { $gte: 25 } } ).sort({"qty":-1})

4. $lt/$lte

Syntax: {field: {$lt: value} }

//查询结果降序
db.inventory.find( { qty: { $lte: 20 } } ).sort({"qty":-1})

5. $ne

Syntax: {field: {$ne: value} }

db.inventory.find( { qty: { $ne: 20 } } ).sort({"qty":-1})

6. $in

其实和sql中的in操作是一样的。。。where id in (1,2,3,4,5)

7: $nin
//db.inventory.update({ tags: { $in:["A","E"]} },{$set: { qty:100000000 }})
db.inventory.find( { qty: { $nin: [ 5, 20 ] } } ).sort({"qty":-1});

(6)逻辑运算符
一:逻辑运算符
or,and,not

1,$or, $and,$not,$nor

二:详解
https://docs.mongodb.com/v3.2/reference/operator/query-logical/
1. $or select * from users where id=1 or name='jack'

{$or:[{},{}]} //组织json。
例子:
db.inventory.find({$or:[{"item.name":"ab"},{"qty":20}]})
db.inventory.find({$or:[{"item.name":"ab"},{"qty":15}]})

模型: $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }

$or 和 $in

如果$or在同一个字段上进行多次,官方建议使用$in操作。。。

2.$and select * from users where id=1 and name='jack'

{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }

db.inventory.find({$and:[{"item.name":"ab"},{"qty":{$gt:4}}]});

3.$not

{ field: { $not: { <operator-expression> } } }

找到 exression的反向操作。

db.inventory.find({"qty":{$not:{$lt:10}}}).sort({"qty":-1});

4.$nor操作

$not 等于 not or 操作。。。

{ $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] }

db.inventory.find({$nor:[{"qty":{$gt:10}}]});

db.inventory.find({$or:[{"qty":{$gt:10}}]});

两个集合一直都是互补的关系。。。

5. $exists

Syntax: { field: { $exists: <boolean> } }

MongoDB $exists does not correspond to SQL operator exists. For SQL exists, refer to the $in operator.

exists => hasfield(""); => true/false

存在这个字段就取出来
db.inventory.find({"tags":{$exists:true}})

这个得益于document的无模式,不然的话也不会有这个一个字段。。。

6. $type typeof C#/Java

{ field: { $type: <BSON type number> | <String alias> } }

(7)评估运算

一:评估运算 https://docs.mongodb.com/v3.2/reference/operator/query-evaluation/ 1.$mod VB中有这么一个关键字。。 C#/Java =》 %

{"field":{$mod:[ele1,ele2]}}

查找除于4余数为0的所有记录
db.inventory.find( { qty: { $mod: [ 4, 0 ] } } )

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

2. $regex

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }

db.getCollection('inventory').find({})

例子:
查找ab不区分大小写
db.inventory.find({"item.name":{$regex:/ab/i}})

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

怎么去组合,要大家在课下自己去练习。。。

3. $text 【全文索引,因为不支持中文】 中文分词很麻烦的。。。 词库+trietree 字典树 (用处不大,不支持中文)

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

必须先对一个字段进行全文索引,倒排索引。。。

4. $where
非常强大的遍历器,通过function的模式,一排一排的去找最后的数据。。。。
最灵活,也是性能比较差的模式。。。【不走索引】,全表扫描。。。
db.articles.find(
{
$where:function(){
return this.author=="abc" && this.views==200; //this就是当前的迭代文档
}
}
);

//只要我们会js,这些所有的in,notin都是很方便解决的。。。。

db.mytest.find(
{
$where:function(){
return this.item.name=="ab";
}
}
);

5. $all => $and,$in。。。 C# all,any linq的一些方法

{ <field>: { $all: [ <value1> , <value2> ... ] } }

db.mytest.find(
{"tags":{$not:{$all:["A","B"]}}}
);

db.mytest.find(
{"tags":{$all:["A","B"]}}
);

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

6. 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 } ] }

db.survey.find(
{ results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } }
)

例子2:
{ _id: 1, results: [ 82, 85, 88 ] }
{ _id: 2, results: [ 75, 88, 89 ] }

查找80<=results<85 只要有一条记录满足条件即可

db.scores.find(
{ results: { $elemMatch: { $gte: 80, $lt: 85 } } }
)

最终结果为 { _id: 1, results: [ 82, 85, 88 ] }

6. $elemMatch

对array进行条件过滤

或者另外一种写法:
db.scores.find(
{$where:function(){
for(var i in this.results){
return this.results[i]>80 && this.results[i]<85;
}
return false;
}
}
);

7. $size

db.scores.find(
{$where:function(){
return this.results.length==3;
}
}
)

db.collection.find( { field: { $size: 2 } } );
(8)update statement 操作
一:update原子性运算符【Fileds】
1. $inc

redis increase

{$inc:{"filed":""},{..},{...}}           SOA json作为两方的交互手段。。。

mongodb强大的一个好处就是可以用document来解释万物。。。

例子:
{
_id: 1,
sku: "abc123",
quantity: 10,
metrics: {
orders: 2,
ratings: 3.5
}
}

db.products.update(
{ sku: "abc123" },
{ $inc: { quantity: -2, "metrics.orders": 1 } }
)

运行后结果为:
{
"_id" : 1,
"sku" : "abc123",
"quantity" : 8,
"metrics" : {
"orders" : 3,
"ratings" : 3.5
}
}

《1》 $inc 递增不存在的字段回事什么样??

2. $mul

{ $mul: { field: <number> } }

《1》 如果mul的字段不存在,默认给一个default值。。。

《2》 存在就拿filed * number 。。。。(parameter)。
例子:
先要对那条记录进行更新
{ _id: 1, item: "ABC", price: 10.99 }

db.products.update(
{ _id: 1 },
{ $mul: { price: 1.25 } }
)
结果为:
{ _id: 1, item: "ABC", price: 13.7375 }

3. $rename

{$rename: { <field1>: <newName1>, <field2>: <newName2>, ... } }

<1> top-level document

<2> embedded document

原始数据:
{
"_id": 1,
"alias": [ "The American Cincinnatus", "The American Fabius" ],
"mobile": "555-555-5555",
"nmae": { "first" : "george", "last" : "washington" }
}

{
"_id": 2,
"alias": [ "My dearest friend" ],
"mobile": "222-222-2222",
"nmae": { "first" : "abigail", "last" : "adams" }
}

{
"_id": 3,
"alias": [ "Amazing grace" ],
"mobile": "111-111-1111",
"nmae": { "first" : "grace", "last" : "hopper" }
}

操作: db.students.updateMany( {}, { $rename: { "nmae": "name" } } )

结果为:
{
"_id": 1,
"alias": [ "The American Cincinnatus", "The American Fabius" ],
"mobile": "555-555-5555",
"name": { "first" : "george", "last" : "washington" }
}

{
"_id" : 2,
"alias" : [ "My dearest friend" ],
"mobile" : "222-222-2222",
"name" : { "first" : "abigail", "last" : "adams" }
}

{ "_id" : 3,
"alias" : [ "Amazing grace" ],
"mobile" : "111-111-1111",
"name" : { "first" : "grace", "last" : "hopper" } }

4. $setOnInsert

db.collection.update(
<query>,
{ $setOnInsert: { <field1>: <value1>, ... } },
{ upsert: true }
)

如果查询没有结果,那么我们用$setOnInsert作为insert的document。。。
我们的update 和 insert 是一个原子性的操作。【原子性】

原始数据:/* 1 */
{
"_id" : 1,
"sku" : "abc123",
"quantity" : 8.0,
"metrics" : {
"orders" : 3.0,
"ratings" : 3.5
}
}

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

最终结果为:
/* 1 */
{
"_id" : 1,
"sku" : "abc123",
"quantity" : 8.0,
"metrics" : {
"orders" : 3.0,
"ratings" : 3.5
},
"item" : "apple"
}

一:$set操作

{ $set: { <field1>: <value1>, ... } }

<1> 存在 或者不存在的两种情况。。。

<2> 不存在:如果不存在我们就add。。。

二:unset操作。。

{ $unset: { <field1>: "", ... } }
The $unset operator deletes a particular field.
To specify a <field> in an embedded document or in an array, use dot notation.
我们可以delete 普通的字典,还可以delete embeded,array。。。。
删除普通的字段:db.user.update({"_id":1},{$unset:{"nae":""}})

删除内嵌的文档:db.user.update({"_id":1},{$set:{"nae.jack":"jack"}})

db.user.update({"_id":1},{$set:{"status":"b"}})

/* 1 */
{
"_id" : 1.0,
"status" : "b",
"lastModified" : ISODate("2016-07-18T16:09:19.906+08:00"),
"price" : 75.0,
"my" : {
"test11" : 5.0
},
"price11" : 0.0
}

/* 2 */
{
"_id" : 2.0,
"nae" : "jack"
}

三:$min [less than]

看起来就聚合操作中的$min,其实呢???

The $min updates the value of the field to a specified value if the specified value is less than the current value of the field.

{ $min: { <field1>: <value1>, ... } }

就是说 如何value 小于 filed1,那么将会执行: fields=value1...

db.user.update({"_id":1},{$min:{"price":30}})

原数据:
{ _id: 1, highScore: 800, lowScore: 150 }

更新:
db.scores.update( { _id: 1 }, { $min: { lowScore: 250 } } )

结果为:
{ _id: 1, highScore: 800, lowScore: 150 }

四:$max [greater than]

五:$currentDate

就是当前时间。和update有什么关心,难道是将date改成成currentdate????

{ $currentDate: { <field1>: <typeSpecification1>, ... } }

db.user.update({"_id":1},{$currentDate:{"mydate":{$type:"date"}}})

db.user.find();
看官网吧:https://docs.mongodb.com/v3.2/reference/operator/update/currentDate/

(9)update array操作
一:Array操作中的一些操作符

1. $ placeholder

{ "<array>.$" : value }

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

db.students.find()
#####
db.getCollection('student').find({})

db.student.update(
{_id:1,grades:80},
{$set:{"grades.$":87}}

);

2. $addtoSet

C#/java Hashset/Set

{ $addToSet: { <field1>: <value1>, ... } }

将元素添加到我们的array数组中。。。

db.test.update(
{ _id: 9 },
{ $addToSet: {letters: [ "c", "d" ] } }
)

结果为:
{
"_id" : 9,
"letters" : [
"a",
"b",
[
"c",
"d"
]
]
}

3. $pop

-1表示腾出第一个元素

{ $pop: { <field>: <-1 | 1>, ... } }

原数据
{ _id: 1, scores: [ 8, 9, 10 ] }

执行后
db.students.update( { _id: 1 }, { $pop: { scores: -1 } } )

结果为:
{ _id: 1, scores: [ 9, 10 ] }

4. $pullAll

push /pull

删除指定的Array中的数据。。。

{ $pullAll: { <field1>: [ <value1>, <value2> ... ], ... } }

db.students.update(
{"_id":1},
{$pullAll:{"grades":[10,40]}}
);

例子:
原始数据:
{ _id: 1, scores: [ 0, 2, 5, 5, 1, 0 ] }

执行命令:
db.survey.update( { _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } } )

结果为:
{ "_id" : 1, "scores" : [ 2, 1 ] }

5.$pull

这个删除是通过制定的条件去删除。。。

{ $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }

例子:
{ _id: 1, votes: [ 3, 5, 6, 7, 7, 8 ] }

db.profiles.update( { _id: 1 }, { $pull: { votes: { $gte: 6 } } } )

结果为:
{ _id: 1, votes: [ 3, 5 ] }

6.pushAll

{ $pushAll: { <field>: [ <value1>, <value2>, ... ] } }

7. push

{ $push: { <field1>: <value1>, ... } }

$push 和 $each 搭档

db.students.update(
{"_id":1},
{$push:{"grades":{$each:[100,200,300]}}}
);

db.students.find();

一:Array操作续

1.$each

$each 和 $addToSet 和 $push一起使用。。。

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

db.students.update(
{"_id":1},
{$addToSet:{"grades":{$each:[100,200,300]}}}
);

{
"_id" : 1,
"alias" : [
"The American Cincinnatus",
"The American Fabius"
],
"mobile" : "555-555-5555",
"name" : {
"first" : "george",
"last" : "washington"
},
"grades" : [
100.0,
200.0,
300.0,
150.0,
250.0,
350.0
]
}

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

2.$slice

$slice 和 $push 是一起使用的。。。

slice: -5表示取倒数后面5个
例子:
{ "_id" : 1, "scores" : [ 40, 50, 60 ] }

db.students.update(
{ _id: 1 },
{
$push: {
scores: {
$each: [ 80, 78, 86 ],
$slice: -5
}
}
}
)

结果为:
{ "_id" : 1, "scores" : [ 50, 60, 80, 78, 86 ] }

js 也是有$slice的函数。。。

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

db.students.update(
{"_id":1},
{
$push:
{
"grades":
{$each:[600],$slice:2}
}
}
);

db.students.find();

3. $sort

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

db.students.update(
{"_id":1},
{
$push:
{
"grades":
{$each:[100,200,350],$sort:1}
}
}
);

db.students.find();

4. $position [位置的含义]

{
$push: {
<field>: {
$each: [ <value1>, <value2>, ... ],
$position: <num>
}
}
}
db.students.update(
{"_id":1},
{
$push:
{
"grades":
{$each:[150],$position:1}
}
}
);

db.students.find();

5. $bit

java,C# 都是bit的概念。。。

int 32位

0 0 0 0 0 .....0 0 0 0

& 0 0 0 0 .....0 0 0 0

就是在这些bit位上做一些手脚。。。
bitmap 【百度一个经典的面试题】 去重。O(1)的时间。

0 0 1 0 => 2

& 1 0 0 1 => 9

& 0 0 0 0 => 0

| 1 0 1 1 => 11

xor1 0 1 1 => 11

是一个技巧性的东西。。。

{ $bit: { <field>: { <and|or|xor>: <int> } } }

比较常用和比较基础的运算符。。。

group, mapreduce 聚合框架

(10)CURD操作

Create,Update,Read,Delete。。。

db.collection.insert()

db.collection.insertOne() New in version 3.2

db.collection.insertMany() New in version 3.2

insert操作的三个方法 ,, insert insertone insertmany。。。
例子:
db.users.insert(
[
{ name: "bob", age: 42, status: "A", },
{ name: "ahn", age: 22, status: "A", },
{ name: "xi", age: 34, status: "D", }
]
)

db.users.insert(
{
name: "sue",
age: 19,
status: "P"
}
)

db.users.insertMany(
[
{ name: "bob", age: 42, status: "A", },
{ name: "ahn", age: 22, status: "A", },
{ name: "xi", age: 34, status: "D", }
]
)

db.users.insertOne(
{
name: "sue",
age: 19,
status: "P"
}
)

find操作 (read)

find
findAndModify
findOne
findoneAndDelete => modify 衍生出来的
findOneAndReplace => modify 中衍生出来的 ,具有集合性质的替换
findoneAndUpdate
例子:
db.users.find( {} ) 等价于 db.users.find()
db.users.find( { status: "A" } )
db.users.find( { status: { $in: [ "P", "D" ] } } )
db.users.find( { status: "A", age: { $lt: 30 } } )

db.users.find(
{
$or: [ { status: "A" }, { age: { $lt: 30 } } ]
}
)

db.users.find( { "favorites.artist": "Picasso" } )

第一个:批量的操作 把find + modify 用在一个事务里面。。。

delete操作 

  remove
deleteOne
deleteMany

if (justOne) {
removeOp.removeOne();
} else {
removeOp.remove();
}
db.users.remove({}) //删除collection users 所有记录document

从代码中可以看到,到底是执行deleteone还是deletemany取决于justOne这个参数。。

update操作

update()
updateOne()
updateMany()
replaceOne()

update() 你一定要记住,它默认是更新一条。。。

常规印象中的update是更新多条。。。sqlserver mysql

if (multi) {
updateOp.update(obj);
} else {
updateOp.updateOne(obj);
}

例子:
db.users.updateOne(
{ "favorites.artist": "Picasso" },
{
$set: { "favorites.food": "pie", type: 3 },
$currentDate: { lastModified: true }
}
)

db.users.replaceOne(
{ name: "abc" },
{ name: "amy", age: 34, type: 2, status: "P", favorites: { "artist": "Dali", food: "donuts" } }
)

bulk操作

bulk操作 mongodb支持的一个批量的操作。

二阶段提交【达到事务性】

介绍网络的带宽,提高性能。。 10个operator 。。 pipeline

否则我们要链接10次mongodb。。。 现在我们只需要一次就ok了。。。

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);
}

If an error occurs during the processing of one of the write operations, MongoDB will continue to process remaining write operations in the list.

(11)mongodb索引
一:mongodb的索引操作。。。

index: 目的是什么。。。 加速查找, (mysql,sqlserver)

mysql: 单键索引

复合索引 多个字段的组合,注意顺序

hash索引 (sqlserver) Dictionary/HashTable/HashMap/Set

索引的实现原理: BTree。。。
二:看一下mongodb中可以支持哪些索引。。。

Single Field 单键索引

Compound Index 复合索引

Multikey Index 多键值索引

Geospatial Index 地理索引

Text Indexes 全文索引

Hashed Indexes hash索引 O(1)的查找,,, 毕竟hash就是为了做定值查找的。。。

Unique Indexes 唯一索引

Sparse Indexes 稀疏索引

TTL Indexes 过期索引 【非常重要】 我们就可以用这个做定时过期的效果。。。
Cache的效果

三:如何创建索引

db.collection.createIndex(keys, options)
例子:造数据
var a=[];
for(var i= 10 ;i<10000;i++){
var name="jack"+i;
var age= parseInt(Math.random()*100000%100);
print(age);

a.push({"name":name,"age":age})
}

print(a.length);

db.person.insert(a);

<1> 单键索引: db.person.createIndex({"age":1})

db.person.find({"age":45}).explain()
"stage" : "IXSCAN": 表示走索引
"stage" : "COLLSCAN": 表示走全表扫描

"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0
},

"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"name" : {
"$eq" : "jack1000"
}
},
"direction" : "forward"
},

###########
走索引的例子:
db.person.find({"age":45}).explain()

/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.person",
"indexFilterSet" : false,
"parsedQuery" : {
"age" : {
"$eq" : 45.0
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0
},
"indexName" : "age_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[45.0, 45.0]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}
#######
走全表扫描的例子:

db.person.find({"name":"jack20"}).explain();
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.person",
"indexFilterSet" : false,
"parsedQuery" : {
"name" : {
"$eq" : "jack20"
}
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"name" : {
"$eq" : "jack20"
}
},
"direction" : "forward"
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

<2> 复合索引

一定要注意顺序。。 哪个字段在前,哪个字段在后都有严格的区别。。。

你创建一个: name + age 的索引

但是,我查询是通过age作为前缀条件,那么这时候是走不了 name_1 这个索引的 。。。

而是情愿采用 全表扫描。。。

创建联合索引:
db.person.createIndex({"age":1,"name":1})

db.person.find({"age":8}).sort({"age":1}).explain("executionStats")

/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.person",
"indexFilterSet" : false,
"parsedQuery" : {
"age" : {
"$eq" : 8.0
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0
},
"indexName" : "age_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[8.0, 8.0]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0,
"name" : 1.0
},
"indexName" : "age_1_name_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[8.0, 8.0]"
],
"name" : [
"[MinKey, MaxKey]"
]
}
}
}
]
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

查询顺序:
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.person",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : [
{
"age" : {
"$eq" : 8.0
}
},
{
"name" : {
"$eq" : "jack126"
}
}
]
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0,
"name" : 1.0
},
"indexName" : "age_1_name_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[8.0, 8.0]"
],
"name" : [
"[\"jack126\", \"jack126\"]"
]
}
}
},
"rejectedPlans" : [
{
"stage" : "FETCH",
"filter" : {
"name" : {
"$eq" : "jack126"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0
},
"indexName" : "age_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[8.0, 8.0]"
]
}
}
}
]
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

一:多键值索引

其实所谓的多键值索引就是在array上面建立一个索引,mongodb会将array的每一个数字进行排序【索引】。。。。

比较奇葩的索引的方式, mysql,sqlserver中都是不存在。。

1. 创建方式

db.coll.createIndex( { <field>: < 1 or -1 > } ) single fields 创建方式是一样的。

db.plane.createIndex({"ratings":1})

db.plane.find()

db.plane.find({"ratings":[5,9]}).explain()

例子: "isMultiKey" : true 表示多键值索引!!!!!!!
/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.MulKeyIndex",
"indexFilterSet" : false,
"parsedQuery" : {
"ratings" : {
"$eq" : [
5.0,
9.0
]
}
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"ratings" : {
"$eq" : [
5.0,
9.0
]
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"ratings" : 1.0
},
"indexName" : "ratings_1",
"isMultiKey" : true,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"ratings" : [
"[5.0, 5.0]",
"[[ 5.0, 9.0 ], [ 5.0, 9.0 ]]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

二:Hash索引

提到hash索引,mysql中也是有hash的。。。

C#/Java Map/HashSet/HashTable

将字段的之通过hash函数变成一个int类型的一个数字。。。 %int.MaxValue
最终放到数组中。。。

1. 创建方式:

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

sharded cluster 我们是支持 hashed index

同时大家要知道,hash就是为了定值查找。

Hashing Function O(1) 如果function比较懒,那么就容易造成 冲突 和 挂链。。。

"executionStats":查看执行时间

db.person.find({"age":8}).sort({"age":1}).explain("executionStats")

/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.plane",
"indexFilterSet" : false,
"parsedQuery" : {
"item" : {
"$eq" : "eee"
}
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"item" : {
"$eq" : "eee"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"item" : "hashed"
},
"indexName" : "item_hashed",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[6782435454978459636, 6782435454978459636]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"item" : {
"$eq" : "eee"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 1,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"item" : "hashed"
},
"indexName" : "item_hashed",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"item" : [
"[6782435454978459636, 6782435454978459636]"
]
},
"keysExamined" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "localhost.localdomain",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

####例子:
var a=[];
for(var i=0;i<10000;i++){
var name="jack"+i;
a.push({"name":name});
}

print(a.length);
db.hashIndex.insert(a);
db.hashIndex.find({"name":"jack10000"}).explain("executionStats"); //4
db.hashIndex.createIndex({"name":"hashed"})
db.hashIndex.find({"name":"jack1000"}).explain("executionStats"); //1

/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.hashIndex",
"indexFilterSet" : false,
"parsedQuery" : {
"name" : {
"$eq" : "jack1000"
}
},
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"name" : {
"$eq" : "jack1000"
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"name" : "hashed"
},
"indexName" : "name_hashed",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"name" : [
"[5511545636345377563, 5511545636345377563]"
]
}
}
},
"rejectedPlans" : []
},
"executionStats" : {
"executionSuccess" : true,
"nReturned" : 1,
"executionTimeMillis" : 0,
"totalKeysExamined" : 1,
"totalDocsExamined" : 1,
"executionStages" : {
"stage" : "FETCH",
"filter" : {
"name" : {
"$eq" : "jack1000"
}
},
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"docsExamined" : 1,
"alreadyHasObj" : 0,
"inputStage" : {
"stage" : "IXSCAN",
"nReturned" : 1,
"executionTimeMillisEstimate" : 0,
"works" : 2,
"advanced" : 1,
"needTime" : 0,
"needYield" : 0,
"saveState" : 0,
"restoreState" : 0,
"isEOF" : 1,
"invalidates" : 0,
"keyPattern" : {
"name" : "hashed"
},
"indexName" : "name_hashed",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"name" : [
"[5511545636345377563, 5511545636345377563]"
]
},
"keysExamined" : 1,
"dupsTested" : 0,
"dupsDropped" : 0,
"seenInvalidated" : 0
}
}
},
"serverInfo" : {
"host" : "node2",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

3: partial indexes 【New in version 3.2】

局部索引。。 mysql和sqlserver 都是没有的。。。

如果你是一个basic indexes。。。 你检索的索引是针对所有的文档。。。。

既然有所有,那么就有相对的词: 局部。。。

Partial indexes only index the documents in a collection that meet a specified filter expression.

Create a Partial Index

db.restaurants.createIndex(
{ cuisine: 1, name: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)

db.restaurants.createIndex(
{ cuisine: 1, name: 1 },
{ partialFilterExpression: { rating: { $gt: 5 } } }
)

db.person.createIndex(
{ "age": 1, },
{ partialFilterExpression: { "age": { $gt: 600 } } }
)

db.person.find({"age":820}).explain("executionStats")

可以用到更少的存储空间,多少的性能开销。。。。。

例子:
var a=[];
for(var i= 10 ;i<10000;i++){
var name="jack"+i;
var age= parseInt(Math.random()*100000%100);
print(age);

a.push({"name":name,"age":age})
}

print(a.length);

db.partialIndex.insert(a);

db.partialIndex.createIndex(
{ "age": 1, },
{ partialFilterExpression: { "age": { $gt: 600 } } }
)

db.partialIndex.find({"age":820}).explain("executionStats") //走索引
db.partialIndex.find({"age":120}).explain("executionStats") //走全表扫描

一: sparse index 【稀疏索引】

三个document一点关系都没有,除了主键ID是一样的。。。

这样的documents怎么建立索引。。。

稀疏索引: 他的意思就是我建立的index字段必须在有这个字段的document上才可以建立。

The index skips over any document that is missing the indexed field.

总体上说和partial indexs 有一点像,都是一种局部性质的。。。

1. 创建方式

db.hotel.createIndex( { "age": 1 }, { sparse: true } )

db.hotel.find()

db.hotel.find({"age":20}).explain()

/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "ctrip.hotel",
"indexFilterSet" : false,
"parsedQuery" : {
"age" : {
"$eq" : 20.0
}
},
"winningPlan" : {
"stage" : "FETCH",
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"age" : 1.0
},
"indexName" : "age_1",
"isMultiKey" : false,
"isUnique" : false,
"isSparse" : true,
"isPartial" : false,
"indexVersion" : 1,
"direction" : "forward",
"indexBounds" : {
"age" : [
"[20.0, 20.0]"
]
}
}
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "localhost.localdomain",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

2. unique index
不向大家介绍了。。

3. TTL indexes

TTL indexes are special single-field indexes that MongoDB can use to automatically remove documents from a collection after a certain amount of time.

a certain amount of time

叫做缓存。。。指定时间过期。。。

1. 营销活动,给用户发送短信和邮件。。。。

千人千面:【快消品】

用户下单的时候:发送一封推荐的邮件。。。 ”猜你喜欢“。

既然收货成功,肯定是认可这个产品的。。。

收货成功的时候:再发送一封推荐的邮件。。。”第二波营销”。

订单贷款:【10天的收获期】

第一次下单: 会把已经下单的人数据塞到我们的collections。。。 同时设置一个过期时间:11天。。。

第二次下单: 我只会根据前10天这个时间段获取到数据,然后发送第二波。。。

7.22 => 7.12

7.23 => 7.13 这个时候7.12的数据自动踢掉了。。。

这样的话,我们就不需要手动去剔除数据。。。

2. 怎么创建:
db.eventlog.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )

字段:必须是“时间”

过期的秒数: expireAfterSeconds: 3600

3. 我们发现有延迟,现在查找一下这个延迟的原因

A background thread in mongod reads the values in the index and removes expired documents from the collection.

The background task that removes expired documents runs every 60 seconds. As a result, documents may remain in a collection during the period between the expiration of the document and the running of the background task.

我们的background tasks 60s 执行一次。。。 实时执行会有性能问题。。。。

(12)管理索引
一:索引的管理 【manage indexes】 CURD操作。。
《1》 Views Indexes

1. 查看collections中的所有索引。。。
db.person.getIndexes()

2. 查看db中的所有索引。。。 foreach

db.getCollectionNames().forEach(function(collection) {
indexes = db[collection].getIndexes();
print("Indexes for " + collection + ":");
printjson(indexes);
});

[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "ctrip.hashIndex"
},
{
"v" : 1,
"key" : {
"name" : "hashed"
},
"name" : "name_hashed",
"ns" : "ctrip.hashIndex"
}
]

pintjson( db.getCollectionNames())//查看所有索引:
[
"MulKeyIndex",
"articles",
"hashIndex",
"inventory",
"logs",
"mylog",
"order",
"partialIndex",
"person",
"plane",
"products",
"scores",
"student",
"students",
"survey",
"test",
"users"
]

pintjson( db.getCollectionNames())
var dblist=db.getCollectionNames();

dblist.forEach(function(dbname){
print(dbname);
var indexlist=db[dbname].getIndexes();
printjson(indexlist);
});

《2》 Remove Indexes

db.collection.dropIndex()

我们指定删除的字段。。。

You can also use the db.collection.dropIndexes() to remove all indexes, except for the _id index from a collection.

《3》 Modify an Index

delete => add

rebuild 【碎片清理】

《4》 Rebuild Indexes

replica sets 主从备份。。。 如果primary关掉了,,从顶上去。。。

(13)mongodb查询计划
一:Query Plan

1. 如何去优化query和建立index。。

在mongodb中我们使用explain去查看执行计划的。。。

Plan Cache /Cache Plan

winning plan 若干个执行计划中挑选一个作为胜出者。

/* 1 */
{
"queryPlanner" : {
"plannerVersion" : 1,
"namespace" : "datamip.person",
"indexFilterSet" : false,
"parsedQuery" : {
"$and" : []
},
"winningPlan" : {
"stage" : "COLLSCAN",
"filter" : {
"$and" : []
},
"direction" : "forward"
},
"rejectedPlans" : []
},
"serverInfo" : {
"host" : "localhost.localdomain",
"port" : 27017,
"version" : "3.2.8",
"gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
},
"ok" : 1.0
}

The plan cache does not persist if a mongod restarts or shuts down.

二:index的建议 Indexing Strategies

1. 你创建的索引最好能够覆盖大多数的查询。。。

{ "category": 1, "item": 1 }

可以用: category做前缀

也可以用:category + item

千万不要: item + category 这种模式。。。

2. sort的时候最好sort的键也要在索引上面。。。

3. ensure index fit in RAM

When your index fits in RAM, the system can avoid reading the index from disk and you get the fastest processing.

最好的建议是我们的index最好都能够存储在内存中。。。

db.collection.totalIndexSize()

我们的操作获取最近的插入数据比较多。。这时候我们可以不必讲究所有的indexes都放在
内存中。。。

日志:的场景

4. 确保索引的高选择性

比如说10个index,其中有1,2index基本上不是不被选中的,,那么这个索引基本上就没什么用了。。。

(14)mongodb GridFS

一:GridFS => Grid File System + sharding 分布式的文件系统

TFS => Taobao File System...

HDFS => Hadoop File System...

天然具有哪些功效: 1. 多机器存储,备份。。。

2. 可以突破一般文件系统对 files的限制。。。

3. 分段存储,不像普通的file system 整个存储。。。

GridFS is a specification for storing and retrieving files that exceed the BSON-document size limit of 16 MB.

二: 通过mongodfiles 导入一个file【video,img】来进行测试。。。

1. mongofiles。。

2. 我们各自语言的驱动来实现。。 C#/Java/nodejs

mongofiles <options> <commands> <filename>

--host

mongodb做到一个绝对的内网环境。。。--username --password

3. --db <database>, -d <database>

也就是说我们的file放到哪一个db中去。。。

3. --local <filename>, -l <filename>

操作列表:【CURD】

list <prefix>

search <string>

put <filename>

get <filename>

get_id "<ObjectId>"

delete <filename>

delete_id "<ObjectId>"

[root@localhost bin]# ./mongofiles -d records put jobs.exe
2016-07-23T21:45:28.257-0700 connected to: localhost
added file: ./jobs.exe

[root@node2 bin]# ./mongofiles -d records put ../newViewer.exe
2017-03-16T05:18:54.830+0800 connected to: localhost
added file: ../newViewer.exe

当你导入file的时候,grid会在指定的db上面生成两个collection

1. fs.chuncks

memcache,其实里面有一个chunck。。。 大小是255字节

2. fs.files

记录了job.exe 的简要信息。。。

50.7 M 用了 204 chunck 【分段存储】

查找命令:
db.fs.chunks.find({});
db.fs.files.find({});

(15) mongodb aggregation
一:aggregation pipeline
官网地址: https://docs.mongodb.com/manual/reference/operator/aggregation-pipeline/
1. 管道模型。。。

后面操作的数据源是来自于前一个操作。。。

2. 常见的方式,我们用aggregation做什么? 聚合操作。 $group。

从我们看到的$group,我们就可以认为 aggreation比group更加强大。。。

aggregation 可以多机器跨越查询。。 group做不到的。。

《1》 $project 相当于我们sql操作的 select

《2》 $match 相当于我们的 where

《3》 $limit 相当于我们sql操作的 limit

《4》 $skip

《5》 $unwind 将数据拆解成每一个document。。。

《6》 $group 这个就是分组计算的。

《7》 $sample 随机选择文档

《8》 $sort sql中的desc asc。

《9》 $geoNear 经纬度。

《10》$lookup sql中的join操作

《11》$out 将最后的结果输出到指定的collection中去。。

《12》$indexStats 查询过程中的索引情况。。

《13》$redact: 决定内嵌文档是否keep。。

有时候我们想用mongodb做一些collection的关联。。。

db.collection.aggregate(pipeline, options)

一:$lookup讲解

{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}

例子:
orders :
{ "_id" : 1, "item" : "abc", "price" : 12, "quantity" : 2 }
{ "_id" : 2, "item" : "jkl", "price" : 20, "quantity" : 1 }
{ "_id" : 3 }

inventory :

{ "_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": null, description: "Incomplete" }
{ "_id" : 6 }

db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
}
])

结果为:
/* 1 */
{
"_id" : 1,
"item" : "abc",
"price" : 12,
"quantity" : 2,
"inventory_docs" : [
{
"_id" : 1,
"sku" : "abc",
"description" : "product 1",
"instock" : 120
}
]
}

/* 2 */
{
"_id" : 2,
"item" : "jkl",
"price" : 20,
"quantity" : 1,
"inventory_docs" : [
{
"_id" : 4,
"sku" : "jkl",
"description" : "product 4",
"instock" : 70
}
]
}

/* 3 */
{
"_id" : 3,
"inventory_docs" : [
{
"_id" : 5,
"sku" : null,
"description" : "Incomplete"
},
{
"_id" : 6
}
]
}

二: $match讲解

{ $match: { <query> } }

db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
},
{
$match:{"price":{$gt:0}}
},

])

三:$group

{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

四:$project

{ $project: { <specifications> } }

五:$out

{ $out: "<output-collection>" }

将结果保存到一个collection上面去。。。。

如果不用$out,那么我们的pipeline计算的结果并没有序列化到硬盘。。。

allowDiskUse:非常重要,因为我们的group和sort都有内存100M的限制,所以开启为true的

话,我们就没有100M的限制了。。。。

db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
},
{
$match:{"price":{$gt:0}}
},
{
$group:{"_id":"$item","totalprice":{$sum:"$price"},"quantityAvg":{$avg:"$quantity"}}
},
{
$project:{"_id":1,"totalprice":1}
},
{
$limit:1
},
{
$out:"myaggregate"
}
],
{"allowDiskUse":true})

(16)mongodb轻量级框架group
一:group
文档: https://docs.mongodb.com/manual/reference/command/nav-aggregation/
sqlserver中也是有 group。。。
agrregate pipeline => group操作。。 sharding cluster。。

group 不可以的,同时还有一个100m的限制。。。
mapreduce。。。

{
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结束后插入点。。。。

模板例子:
db.runCommand(
{
group:
{
ns: 'orders',
key: { ord_dt: 1, 'item.sku': 1 },
cond: { ord_dt: { $gt: new Date( '01/01/2012' ) } },
$reduce: function ( curr, result ) { },
initial: { }
}
}
)

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

//db.inventory.find()

db.runCommand(
{
group:
{
ns: 'inventory',
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;
}
}
}
)

$keyf => $key function <=> key

普通的key: 是死条件,不好修改。。。

这时候我们可以用function的形式来替代,增加我们的灵活性。。

javascript。。。。

db.inventory.find()

db.runCommand(
{
group:
{
ns: 'inventory',
//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;
}
}
}
)

二:group的一些官方介绍

1. The group command does not work with sharded clusters. Use the aggregation framework or map-reduce in sharded environments.

2. The result set must fit within the maximum BSON document size.

/* 1 */
{
"_id" : 1,
"sku" : "abc",
"description" : "product 1",
"instock" : 120
}

/* 2 */
{
"_id" : 2,
"sku" : "def",
"description" : "product 2",
"instock" : 80
}

/* 3 */
{
"_id" : 3,
"sku" : "ijk",
"description" : "product 3",
"instock" : 60
}

/* 4 */
{
"_id" : 4,
"sku" : "jkl",
"description" : "product 4",
"instock" : 70
}

/* 5 */
{
"_id" : 5,
"sku" : "abcedfe",
"description" : "product 1",
"instock" : 120
}

/* 6 */
{
"_id" : 6,
"sku" : "def而微软为",
"description" : "product 2",
"instock" : 70
}

/* 1 */
{
"waitedMS" : NumberLong(0),
"retval" : [
{
"description" : 1.0,
"total" : 400.0,
"count" : 5.0,
"avg" : 80.0
}
],
"count" : NumberLong(5),
"keys" : NumberLong(1),
"ok" : 1.0
}

(17)跨库查询MapReduce

(18)mongodb存储引擎
一:wiredtiger

mongodb收购的一个 第三方团队。

We're proud to announce that MongoDB has acquired WiredTiger, and we've joined the MongoDB team!

在3.0之后,我们的mongodb开始指定是否使用wiredtiger, 到3.2之后,wiredtiger已经是默认的存储引擎。

在3.0之前,我们都是用mmap。。(内存文件隐射)

Document Level Concurrency
Snapshots and Checkpoints
Journal
Compression
Memory Use

1. Document Level Concurrency 文档级别的并发。。。 锁 粒度更小

multiple clients can modify different documents of a collection at the same time.

和sqlserver,mysql中的record lock 有点像。

alter database,collection database,collection lock

collection level concurrency 集合级别的并发。。。 锁 粒度更大

2. Snapsshots and Checkpoints 快照和(生成快照点) redis: snapshot,aof

checkpoint: 触发时机: 60s triiger, up to 2G

journal 事务日志的方式。。。如果mongodb挂掉了,mmap会通过事务日志回访来恢复collection。

3. journal: 记录“checkpoint” 和 “checkpoint”的日志记录。
journal: 一直记录着操作日志。。。

4. compression: wiredtiger会对collection,indexes进行压缩。。。 snappy 。zlib。。
none

110G => 30G compression [耗费额外的CPU,benefit:reduce memory]

5. memory use: wiretiger: internal,memorys

Via the filesystem cache, MongoDB automatically uses all free memory that is not used by the WiredTiger cache or by other processes. Data in the filesystem cache is compressed.

mmap: system memorys

二:mmapv1

In the default configuration for the MMAPv1 storage engine, MongoDB writes to the data files on disk every 60 seconds and writes to the journal files roughly every 100 milliseconds。
in-place updates : 原地替换

解决方案: 生成一个document,给两倍的空间。。。 这样的话减少移动。。

三:in-memory enterpirse

Changed in version 3.2.6. 基于内存的存储引擎。。。。 【membercache】有得一拼。

数据丢失。。。 The in-memory storage engine uses document-level concurrency

1. 知道指定的方式:

inMemory for the --storageEngine option, or the storage.engine setting if using a configuration file.

2. 手工去设置占用的内容上限

--inMemorySizeGB

storage.inMemory.engineConfig.inMemorySizeGB setting in the YAML configuration file.

(19)mongodb master-slave安装
官方文档:https://docs.mongodb.com/manual/core/master-slave/

27000 master
27001 slave
27002 slave

master 配置如下:
vim 1.config

port=27000
bind_ip=192.168.175.30
dbpath=/mongodb/master-slave/27000/db
master=true

27001配置文件如下:
port=27001
bind_ip=192.168.175.30
dbpath=/mongodb/master-slave/27001/db
slave=true
source=192.168.175.30:27000

27002配置如下:
port=27002
bind_ip=192.168.175.30
dbpath=/mongodb/master-slave/27002/db
slave=true
source=192.168.175.30:27000

master 启动:mongod --master --dbpath /data/masterdb/
27000master启动:
/mongodb/master-slave/27000/bin/mongod --config=/mongodb/master-slave/27000/1.config

slave 启动:mongod --slave --source <masterhostname><:<port>> --dbpath /data/slavedb/
27001启动: /mongodb/master-slave/27001/bin/mongod --config=/mongodb/master-slave/27001/1.config
27001启动: /mongodb/master-slave/27002/bin/mongod --config=/mongodb/master-slave/27002/1.config

在27000上面执行如下命令
db.isMaster()

/* 1 */
{
"ismaster" : true,
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2017-03-16T03:05:21.087Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1.0
}

从库系统会有 sources文件 记录同步那个ip的数据
/* 1 */
{
"_id" : ObjectId("58c9ff42f8269a58068c91af"),
"host" : "192.168.175.30:27000",
"source" : "main",
"syncedTo" : Timestamp(6397930803363315, 1)
}

(20)mongodb replica set副本集安装

1. master 和 slave 和分发关系,还是通信关系
2. slave 和slave 之间也是有联系的。。。

p2p 模式。。

这里的master 是由 replica set 集合选举出来的。。。 CAP概念。。

zookeeper,redis 都是采用这种投票的机制来选举 master 从众多的

slave之间。。。

mongodb建议我们用 replica set 来代替 master-slave。。。

普通的master-slave 是没有选举关系,slave和slave之间并没有通信。。。

arbiter secondary

前者:不保存数据。。。 voted

后者:他是同步primary 的 data。。。 voted

二:搭建

1. 给集群取一个name。。。

2. 集群的config配置。。。

rs=> replica set ....

3. 可以再添加一个arbiter。。。

配置文件1
port=27100
bind_ip=192.168.175.30
dbpath=/mongodb/replset/27100/db
replSet=ctrip

配置文件2
port=27101
bind_ip=192.168.175.30
dbpath=/mongodb/replset/27101/db
replSet=ctrip

配置文件3
port=27102
bind_ip=192.168.175.30
dbpath=/mongodb/replset/27102/db
replSet=ctrip

分别启动实例:
/mongodb/replset/27100/bin/mongod --config=/mongodb/replset/27100/1.config
/mongodb/replset/27101/bin/mongod --config=/mongodb/replset/27101/1.config
/mongodb/replset/27102/bin/mongod --config=/mongodb/replset/27102/1.config

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

//2. 查看集群的配置
rs.conf()

/* 1 */
{
"_id" : "ctrip",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "192.168.175.30:27100",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1.0,
"tags" : {},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"getLastErrorModes" : {},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("58ca0c11f600ad66f12081c1")
}
}

//3. 像集群中添加members
rs.add("192.168.175.30:27101")
rs.add("192.168.175.30:27102")

rs.status()

在添加一个arbiter仲裁
配置文件4
port=27103
bind_ip=192.168.175.30
dbpath=/mongodb/replset/27103/db
replSet=ctrip

启动:/mongodb/replset/27103/bin/mongod --config=/mongodb/replset/27103/1.config

rs.addArb("192.168.175.30:27103")

rs.status()
最终的配置文件如下:
/* 1 */
{
"set" : "ctrip",
"date" : ISODate("2017-03-16T04:05:00.178Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "192.168.175.30:27100",
"health" : 1.0,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1141,
"optime" : {
"ts" : Timestamp(6397942610228412, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-03-16T04:04:56.000Z"),
"electionTime" : Timestamp(6397939487787188, 2),
"electionDate" : ISODate("2017-03-16T03:52:49.000Z"),
"configVersion" : 4,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.175.30:27101",
"health" : 1.0,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 618,
"optime" : {
"ts" : Timestamp(6397942610228412, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-03-16T04:04:56.000Z"),
"lastHeartbeat" : ISODate("2017-03-16T04:04:58.540Z"),
"lastHeartbeatRecv" : ISODate("2017-03-16T04:04:58.556Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.175.30:27100",
"configVersion" : 4
},
{
"_id" : 2,
"name" : "192.168.175.30:27102",
"health" : 1.0,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 588,
"optime" : {
"ts" : Timestamp(6397942610228412, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-03-16T04:04:56.000Z"),
"lastHeartbeat" : ISODate("2017-03-16T04:04:58.541Z"),
"lastHeartbeatRecv" : ISODate("2017-03-16T04:04:56.557Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "192.168.175.30:27101",
"configVersion" : 4
},
{
"_id" : 3,
"name" : "192.168.175.30:27103",
"health" : 1.0,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 3,
"lastHeartbeat" : ISODate("2017-03-16T04:04:58.547Z"),
"lastHeartbeatRecv" : ISODate("2017-03-16T04:04:56.591Z"),
"pingMs" : NumberLong(0),
"configVersion" : 4
}
],
"ok" : 1.0
}

测试数据:
var a=[];
for(var i= 10 ;i<10000;i++){
var name="jack"+i;
var age= parseInt(Math.random()*100000%100);
print(age);

a.push({"name":name,"age":age})
}

print(a.length);

db.person.insert(a);

下面模拟27000挂掉

查看rs.status()信息如下:
"_id" : 0,
"name" : "192.168.175.30:27100",
"health" : 0.0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",

在启动27000
查看rs.status()信息如下:
/* 1 */
{
"set" : "ctrip",
"date" : ISODate("2017-03-16T04:19:08.242Z"),
"myState" : 2,
"term" : NumberLong(2),
"syncingTo" : "192.168.175.30:27101",
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "192.168.175.30:27100",
"health" : 1.0,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 4,
"optime" : {
"ts" : Timestamp(6397945088424542, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-03-16T04:14:33.000Z"),
"lastHeartbeat" : ISODate("2017-03-16T04:19:07.897Z"),
"lastHeartbeatRecv" : ISODate("2017-03-16T04:19:08.091Z"),
"pingMs" : NumberLong(0),
"configVersion" : 4
},
{
"_id" : 1,
"name" : "192.168.175.30:27101",
"health" : 1.0,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 1436,
"optime" : {
"ts" : Timestamp(6397945088424542, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-03-16T04:14:33.000Z"),
"lastHeartbeat" : ISODate("2017-03-16T04:19:06.878Z"),
"lastHeartbeatRecv" : ISODate("2017-03-16T04:19:06.990Z"),
"pingMs" : NumberLong(0),
"electionTime" : Timestamp(6397945084129574, 1),
"electionDate" : ISODate("2017-03-16T04:14:32.000Z"),
"configVersion" : 4
},
{
"_id" : 2,
"name" : "192.168.175.30:27102",
"health" : 1.0,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 1954,
"optime" : {
"ts" : Timestamp(6397945088424542, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-03-16T04:14:33.000Z"),
"syncingTo" : "192.168.175.30:27101",
"configVersion" : 4,
"self" : true
},
{
"_id" : 3,
"name" : "192.168.175.30:27103",
"health" : 1.0,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 851,
"lastHeartbeat" : ISODate("2017-03-16T04:19:06.878Z"),
"lastHeartbeatRecv" : ISODate("2017-03-16T04:19:06.789Z"),
"pingMs" : NumberLong(0),
"configVersion" : 4
}
],
"ok" : 1.0
}

(21)mongodb sharing cluster安装

27001 mongod 一台
27002 mongod 一台
27004 mongos 一台
27000 configdb 一台

configdb配置如下:
port=27000
bind_ip=192.168.175.30
configsvr=true
dbpath=/mongodb/cluster/27000/db

mongos配置如下
port=27004
bind_ip=192.168.175.30
configdb=192.168.175.30:27000

27001 mongod配置如下:
port=27001
bind_ip=192.168.175.30
dbpath=/mongodb/cluster/27001/db

27002 mongod配置如下:
port=27002
bind_ip=192.168.175.30
dbpath=/mongodb/cluster/27002/db

步骤:
1、开启configdb
/mongodb/cluster/27000/bin/mongod --config=/mongodb/cluster/27000/1.config

2、开启mongos
/mongodb/cluster/27004/bin/mongos --config=/mongodb/cluster/27004/1.config

3、分别开启shard服务器(mongod进程)
/mongodb/cluster/27001/bin/mongod --config=/mongodb/cluster/27001/1.config
/mongodb/cluster/27002/bin/mongod --config=/mongodb/cluster/27002/1.config

//在mongos上面 将mongod进程添加到sharding中
sh.addShard("192.168.175.30:27001")
sh.addShard("192.168.175.30:27002")

//我们最后的分片是对某一个collection的数据进行分片

//在ctrip这个db上面启动分片功能
sh.enableSharding("ctrip")

//在ctrip.plane上面开启分片功能,shard key 是 主键ID
sh.shardCollection("ctrip.plane",{"_id":1});

sh.status()
信息如下:

--- Sharding Status ---
sharding version: {
"_id" : 1,
"minCompatibleVersion" : 5,
"currentVersion" : 6,
"clusterId" : ObjectId("58ca1ae704c69323bc960a7b")
}
shards:
{ "_id" : "shard0000", "host" : "192.168.175.30:27001" }
{ "_id" : "shard0001", "host" : "192.168.175.30:27002" }
most recently active mongoses:
"3.2.8" : 1
balancer:
Currently enabled: yes
Currently running: no
Failed balancer rounds in last 5 attempts: 0
Migration Results for the last 24 hours:
No recent migrations
databases:
{ "_id" : "ctrip", "primary" : "shard0000", "partitioned" : true }
ctrip.plane
shard key: { "_id" : 1 }
unique: false
balancing: true
chunks:
shard0000 1
{ "_id" : { "$minKey" : 1 } } -->> { "_id" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0)

分片的方式:
1. range
2. hash [redis cluster] 就明白了。 16384个slot
3. tag 手工指定分片。。

插数据在 mongos路由的ctrip库上面执行shell

for(var i=0;i<1000;i++){
db.person.insert({"name":"skdnx"+i});
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  入门 mongodb