mongodb_mongodbvue - CSDN
mongodb 订阅
MongoDB是一个基于分布式文件存储 [1]  的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。 展开全文
MongoDB是一个基于分布式文件存储 [1]  的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
信息
特    点
高性能,易部署,易使用
编写语言
由C++语言编写
产品类型
基于分布式文件存储的数据库
外文名
MongoDB
mongodb特点
它的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:*面向集合存储,易存储对象类型的数据。 *模式自由。*支持动态查询。*支持完全索引,包含内部对象。*支持查询。*支持复制和故障恢复。*使用高效的二进制数据存储,包括大型对象(如视频等)。*自动处理碎片,以支持云计算层次的扩展性。*支持 Golang,RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。*文件存储格式为BSON(一种JSON的扩展)。*可通过网络访问。
收起全文
精华内容
参与话题
  • MongoDB数据库从入门到精通

    千人学习 2019-12-18 15:11:50
    本课程是MongoDB数据库的精讲课程,课程从环境搭建开始详细讲述了MongoDB的各个方面,内容涵盖:Mongo shell、数据库CRUD、聚合、索引、数据库模型、MongoDB Java开发和MongoDB Python开发。
  • Mongodb 数据库

    千次阅读 2019-07-24 16:47:57
    mongodb 首先关系型数据库和非关系型数据库的介绍; 对于关系型的数据库,存储数据之前,必须先建表建库,随着数据的复杂度越来越高,所建表的数量也就越来越多 但是非关系型数据库却不需要如此复杂; 关系型数据库...

    后续技术类文档更新到微信公众号-------->>喜欢的扫码关注

    在这里插入图片描述

    mongodb

    首先关系型数据库和非关系型数据库的介绍;
    对于关系型的数据库,存储数据之前,必须先建表建库,随着数据的复杂度越来越高,所建表的数量也就越来越多
    但是非关系型数据库却不需要如此复杂;

    关系型数据库很强大,但是它并不能很好的应付所有的应用场景;
    MySQL的扩展性差;大数据下IO压力大;表结构更改困难。

    mongodb 易扩展,大数据量高性能,灵活的数据模型,高可用。

    mongodb有那些优势;
    1. 易扩展性;nosql数据库的种类繁多;共同的特点就是去掉了关系型数据库的关系型特性;数据之间没有关系
      这样就非常容易扩展。
    2. 大数据。高性能;nosql都具有非常高的读写性能,尤其在大数据量下,同样表现优秀,得益于它的无关系
      性,数据库结构简单;
    3. 灵活的数据模型,不需要为事先存储的数据建立字段,随时可以存储自定义格式的数据,在关系型数据库中
      增删是一件很麻烦的事,如果是一个非常大的数据量的表,增加字段简直就是噩梦。
    mongodb的数据库命令:

    查看当前数据库: db
    查看所有的数据库: show dbs 或者 show databases
    切换数据库: use db_name
    删除当前数据库:db.dropDatabase()

    mongodb的集合命令:

    1, 如果不手动创建集合;向不存在的集合中第一次加入数据的时候,集合会被自动创建出来。

    手动创建集合的命令:
    db.createCollection(name,options)
    db.createCollection(“stu”)
    db.createCollection(“sub”, { capped : true, size : 10 } )
    参数capped: 默认值为false表示不设置上限,值为true表示设置上限
    参数size: 当capped值为true时, 需要指定此参数, 表示上限⼤⼩,当⽂档达到上限时, 会将之前的数据覆盖, 单位为字节
    查看集合:show collections
    删除集合:db.集合名称.drop()

    mongodb常见的数据类型:
    Object ID: ⽂档ID
    String: 字符串, 最常⽤, 必须是有效的UTF-8
    Boolean: 存储⼀个布尔值, true或false
    Integer: 整数可以是32位或64位, 这取决于服务器
    Double: 存储浮点值
    Arrays: 数组或列表, 多个值存储到⼀个键
    Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档
    Null: 存储Null值
    Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数
    Date: 存储当前⽇期或时间的UNIX时间格式

    字符串;
    布尔值;
    整数;
    浮点数;
    数组,列表;
    文档;
    Null;
    时间戳;
    日期;
    九种数据类型 。

    mongodb的数据插入:
    db.集合名称.insert(document)
    db.stu.insert({name:‘gj’,gender:1})
    db.stu.insert({_id:“20170101”,name:‘gj’,gender:1})

    插入文档时候如果不指定id,会自动分配;

    4.2 mongodb的保存
    命令:db.集合名称.save(document) 如果⽂档的_id已经存在则修改, 如果⽂档的_id不存在则添加

    4.3 mongodb的简单查询
    命令:db.集合名称.find()

    4.4 mongodb的更新
    命令:db.集合名称.update( ,,{multi: })

    参数query:查询条件
    参数update:更新操作符
    参数multi:可选, 默认是false,表示只更新找到的第⼀条记录, 值为true表示把满⾜条件的⽂档全部更新
    db.stu.update({name:‘hr’},{name:‘mnc’}) 更新一条
    db.stu.update({name:‘hr’},{KaTeX parse error: Expected 'EOF', got '}' at position 17: …et:{name:'hys'}}̲) 更新一条 db.st…set:{gender:0}},{multi:true}) 更新全部
    注意:“multi update only works with $ operators”

    4.5 mongodb的删除
    命令:db.集合名称.remove(,{justOne: })

    参数query:可选,删除的⽂档的条件
    参数justOne:可选, 如果设为true或1, 则只删除⼀条, 默认false, 表示删除多条
    5. mongodb的高级查询
    知识点:

    掌握mongodb的数据查询操作
    掌握比较运算符的使用
    掌握逻辑运算符的使用
    掌握范围运算符的使用
    了解正则的使用
    掌握skip和limit的使用
    掌握投影方法的使用
    掌握排序方法的使用
    了解去重方法的使用

    5.1 数据查询
    ⽅法find(): 查询

    db.集合名称.find({条件⽂档})

    ⽅法findOne():查询,只返回第⼀个

    db.集合名称.findOne({条件⽂档})

    ⽅法pretty(): 将结果格式化

    db.集合名称.find({条件⽂档}).pretty()

    5.2 比较运算符
    可以使用以下数据进行练习

    {“name” : “郭靖”, “hometown” : “蒙古”, “age” : 20, “gender” : true }
    {“name” : “⻩蓉”, “hometown” : “桃花岛”, “age” : 18, “gender” : false }
    {“name” : “华筝”, “hometown” : “蒙古”, “age” : 18, “gender” : false }
    {“name” : “⻩药师”, “hometown” : “桃花岛”, “age” : 40, “gender” : true }
    {“name” : “段誉”, “hometown” : “⼤理”, “age” : 16, “gender” : true }
    {“name” : “段王爷”, “hometown” : “⼤理”, “age” : 45, “gender” : true }
    {“name” : “洪七公”, “hometown” : “华⼭”, “age” : 18, “gender” : true }
    等于: 默认是等于判断, 没有运算符
    ⼩于:ltlessthanlt (less than) ⼩于等于:lte (less than equal)
    ⼤于:gtgreaterthangt (greater than) ⼤于等于:gte
    不等于:$ne

    例如:

    查询年龄大于18的所有学生
    db.stu.find({age:{$gte:18}})
    5.3 逻辑运算符
    逻辑运算符主要指与、或逻辑

    and:在json中写多个条件即可

    查询年龄⼤于或等于18, 并且性别为true的学⽣
    db.stu.find({age:{KaTeX parse error: Expected 'EOF', got '}' at position 7: gte:18}̲,gender:true}) …or, 值为数组, 数组中每个元素为json

    查询年龄⼤于18, 或性别为false的学⽣
    db.stu.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: or:[{age:{gt:18}},{gender:false}]})

    查询年龄⼤于18或性别为男⽣, 并且姓名是郭靖
    db.stu.find({KaTeX parse error: Expected '}', got 'EOF' at end of input: or:[{age:{gte:18}},{gender:true}],name:‘gj’})
    5.4 范围运算符
    使⽤$in, $nin 判断数据是否在某个数组内

    查询年龄为18、 28的学⽣
    db.stu.find({age:{KaTeX parse error: Expected 'EOF', got '}' at position 14: in:[18,28,38]}̲}) 5.5 ⽀持正则表达式 …regex编写正则表达式

    查询sku以abc开头的数据
    db.products.find({sku:/^abc/})

    查询sku以789结尾的数据
    db.products.find({sku:{regex:789regex:'789’}})
    { “_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” }
    5.6 skip和limit
    ⽅法limit(): ⽤于读取指定数量的⽂档

    db.集合名称.find().limit(NUMBER)
    查询2条学⽣信息
    db.stu.find().limit(2)
    ⽅法skip(): ⽤于跳过指定数量的⽂档

    db.集合名称.find().skip(NUMBER)
    db.stu.find().skip(2)
    同时使用

    db.stu.find().limit(4).skip(5)

    db.stu.find().skip(5).limit(4)
    注意:先使用skip在使用limit的效率要高于前者

    5.7 自定义查询*
    由于mongo的shell是一个js的执行环境 使⽤$where后⾯写⼀个函数, 返回满⾜条件的数据

    查询年龄⼤于30的学⽣
    db.stu.find({
    $where:function() {
    return this.age>30;}
    })
    5.8 投影
    在查询到的返回结果中, 只选择必要的字段

    命令:db.集合名称.find({},{字段名称:1,…})

    参数为字段与值, 值为1表示显示, 值为0不显 特别注意: 对于_id列默认是显示的, 如果不显示需要明确设置为0

    db.stu.find({},{_id:0,name:1,gender:1})

    5.9 排序
    ⽅法sort(), ⽤于对 集进⾏排序

    命令:db.集合名称.find().sort({字段:1,…})

    参数1为升序排列 参数-1为降序排列

    根据性别降序, 再根据年龄升序
    db.stu.find().sort({gender:-1,age:1})
    5.10 统计个数
    ⽅法count()⽤于统计结果集中⽂档条数

    命令:db.集合名称.find({条件}).count() 命令:db.集合名称.count({条件})

    db.stu.find({gender:true}).count()
    db.stu.count({age:{$gt:20},gender:true})
    5.11 消除重复
    ⽅法distinct()对数据进⾏去重

    命令:db.集合名称.distinct(‘去重字段’,{条件})

    db.stu.distinct(‘hometown’,{age:{$gt:18}})

    1. mongodb的常用管道和表达式
      知识点:

    掌握mongodb中管道的语法
    掌握mongodb中管道命令
    2.1 常用管道命令
    在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理 常用管道命令如下:

    $group: 将集合中的⽂档分组, 可⽤于统计结果
    $match: 过滤数据, 只输出符合条件的⽂档
    $project: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
    $sort: 将输⼊⽂档排序后输出
    $limit: 限制聚合管道返回的⽂档数
    skip2.2:skip: 跳过指定数量的⽂档, 并返回余下的⽂档 2.2 常用表达式 表达式:处理输⼊⽂档并输出 语法:表达式:'列名’ 常⽤表达式:

    $sum: 计算总和, $sum:1 表示以⼀倍计数
    $avg: 计算平均值
    $min: 获取最⼩值
    $max: 获取最⼤值
    $push: 在结果⽂档中插⼊值到⼀个数组中

    mongodb创建索引;

    加快查询速度;
    进行数据的去重;

    mongodb创建简单的索引方法
    语法:

    db.集合.ensureIndex({属性:1}),1表示升序, -1表示降序
    db.集合.createIndex({属性:1})
    上面两个命令效果等价
    具体操作:db.db_name.ensureIndex({name:1})

    添加唯一索引的语法:

    db.collection_name.ensureIndex({“name”:1},{“unique”:true})

    删除索引
    语法:db.t1.dropIndex({‘索引名称’:1})

    建立复合索引

    在进行数据去重的时候,可能用一个字段来保证数据的唯一性,这个时候可以考虑建立复合索引来实现。

    例如:抓全贴吧信息,如果把帖子的名字作为唯一索引对数据进行去重是不可取的,因为可能有很多帖子名字相同

    建立复合索引的语法:db.collection_name.ensureIndex({字段1:1,字段2:1})

    python与 mongodb交互:

    from pymongo import MongoClient
    client = MongoClient(host,port)
    collection = client[db名][集合名]
    添加一条数据

    ret = collection.insert_one({“name”:“test10010”,“age”:33})
    print(ret)
    添加多条数据

    item_list = [{“name”:“test1000{}”.format(i)} for i in range(10)]
    insert_many接收一个列表,列表中为所有需要插入的字典
    t = collection.insert_many(item_list)

    查找一条数据

    find_one查找并且返回一个结果,接收一个字典形式的条件
    t = collection.find_one({“name”:“test10005”})
    print(t)
    查找全部数据

    结果是一个Cursor游标对象,是一个可迭代对象,可以类似读文件的指针,但是只能够进行一次读取

    find返回所有满足条件的结果,如果条件为空,则返回数据库的所有
    t = collection.find({“name”:“test10005”})
    #结果是一个Cursor游标对象,是一个可迭代对象,可以类似读文件的指针,
    for i in t:
    print(i)
    for i in t: #此时t中没有内容
    print(i)
    更新一条数据 注意使用$set命令

    update_one更新一条数据
    collection.update_one({“name”:“test10005”},{"$set":{“name”:“new_test10005”}})
    更行全部数据

    update_one更新全部数据
    collection.update_many({“name”:“test10005”},{"$set":{“name”:“new_test10005”}})
    删除一条数据

    delete_one删除一条数据
    collection.delete_one({“name”:“test10010”})
    删除全部数据

    delete_may删除所有满足条件的数据
    collection.delete_many({“name”:“test10010”})

    展开全文
  • MongoDB的简单认识及基本操作

    千次阅读 多人点赞 2019-01-18 19:14:59
    MongoDB 一. 简介 MongoDB是一款强大、灵活、且易于扩展的通用型数据库。 1、易用性 MongoDB是一个面向文档(document-oriented)的数据库,而不是关系型数据库。 不采用关系型主要是为了获得更好得扩展性。当然还有...

    MongoDB

    一. 简介

    MongoDB是一款强大、灵活、且易于扩展的通用型数据库。

    1、易用性

    MongoDB是一个面向文档(document-oriented)的数据库,而不是关系型数据库。
    不采用关系型主要是为了获得更好得扩展性。当然还有一些其他好处,与关系数据库相比,面向文档的数据库不再有“行“(row)的概念取而代之的是更为灵活的“文档”(document)模型。
    通过在文档中嵌入文档和数组,面向文档的方法能够仅使用一条记录来表现复杂的层级关系,这与现代的面向对象语言的开发者对数据的看法一致。
    另外,不再有预定义模式(predefined schema):文档的键(key)和值(value)不再是固定的类型和大小。由于没有固定的模式,根据需要添加或删除字段变得更容易了。通常由于开发者能够进行快速迭代,所以开发进程得以加快。而且,实验更容易进行。开发者能尝试大量的数据模型,从中选一个最好的。
    

    2、易扩展性

    应用程序数据集的大小正在以不可思议的速度增长。随着可用带宽的增长和存储器价格的下降,即使是一个小规模的应用程序,需要存储的数据量也可能大的惊人,甚至超出
    了很多数据库的处理能力。过去非常罕见的T级数据,现在已经是司空见惯了。
    由于需要存储的数据量不断增长,开发者面临一个问题:应该如何扩展数据库,分为纵向扩展和横向扩展,纵向扩展是最省力的做法,但缺点是大型机一般都非常贵,而且
    当数据量达到机器的物理极限时,花再多的钱也买不到更强的机器了,此时选择横向扩展更为合适,但横向扩展带来的另外一个问题就是需要管理的机器太多。
    MongoDB的设计采用横向扩展。面向文档的数据模型使它能很容易地在多台服务器之间进行数据分割。MongoDB能够自动处理跨集群的数据和负载,自动重新分配文档,以及将
    用户的请求路由到正确的机器上。这样,开发者能够集中精力编写应用程序,而不需要考虑如何扩展的问题。如果一个集群需要更大的容量,只需要向集群添加新服务器,MongoDB就会自动将现有的数据向新服务器传送
    

    3、丰富的功能

    MongoDB作为一款通用型数据库,除了能够创建、读取、更新和删除数据之外,还提供了一系列不断扩展的独特功能
    #1、索引
    支持通用二级索引,允许多种快速查询,且提供唯一索引、复合索引、地理空间索引、全文索引
    
    #2、聚合
    支持聚合管道,用户能通过简单的片段创建复杂的集合,并通过数据库自动优化
    
    #3、特殊的集合类型
    支持存在时间有限的集合,适用于那些将在某个时刻过期的数据,如会话session。类似地,MongoDB也支持固定大小的集合,用于保存近期数据,如日志
    
    #4、文件存储
    支持一种非常易用的协议,用于存储大文件和文件元数据。MongoDB并不具备一些在关系型数据库中很普遍的功能,如链接join和复杂的多行事务。省略
    这些的功能是处于架构上的考虑,或者说为了得到更好的扩展性,因为在分布式系统中这两个功能难以高效地实现
    

    4、卓越的性能

    MongoDB的一个主要目标是提供卓越的性能,这很大程度上决定了MongoDB的设计。MongoDB把尽可能多的内存用作缓存cache,视图为每次查询自动选择正确的索引。
    总之各方面的设计都旨在保持它的高性能
    虽然MongoDB非常强大并试图保留关系型数据库的很多特性,但它并不追求具备关系型数据库的所有功能。只要有可能,数据库服务器就会将处理逻辑交给客户端。这种精简方式的设计是MongoDB能够实现如此高性能的原因之一
    

    二. MangoDB基础知识

    在这里插入图片描述

    1、文档是MongoDB的核心概念。文档就是键值对的一个有序集{‘msg’:‘hello’,‘foo’:3}。类似于python中的有序字典。

    需要注意的是:
    #1、文档中的键/值对是有序的。
    #2、文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
    #3、MongoDB区分类型和大小写。
    #4、MongoDB的文档不能有重复的键。
    #5、文档中的值可以是多种不同的数据类型,也可以是一个完整的内嵌文档。文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
    
    文档键命名规范:
    #1、键不能含有\0 (空字符)。这个字符用来表示键的结尾。
    #2、.和$有特别的意义,只有在特定环境下才能使用。
    #3、以下划线"_"开头的键是保留的(不是严格要求的)。
    

    2、集合就是一组文档。如果将MongoDB中的一个文档比喻为关系型数据的一行,那么一个集合就是相当于一张表

    #1、集合存在于数据库中,通常情况下为了方便管理,不同格式和类型的数据应该插入到不同的集合,但其实集合没有固定的结构,这意味着我们完全可以把不同格式和类型的数据统统插入一个集合中。
    
    #2、组织子集合的方式就是使用“.”,分隔不同命名空间的子集合。
    比如一个具有博客功能的应用可能包含两个集合,分别是blog.posts和blog.authors,这是为了使组织结构更清晰,这里的blog集合(这个集合甚至不需要存在)跟它的两个子集合没有任何关系。
    在MongoDB中,使用子集合来组织数据非常高效,值得推荐
    
    #3、当第一个文档插入时,集合就会被创建。合法的集合名:
    集合名不能是空字符串""。
    集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
    集合名不能以"system."开头,这是为系统集合保留的前缀。
    用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
    

    3、数据库:在MongoDB中,多个文档组成集合,多个集合可以组成数据库

    数据库也通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串:
    #1、不能是空字符串("")。
    #2、不得含有' '(空格)、.、$、/、\和\0 (空字符)。
    #3、应全部小写。
    #4、最多64字节。
    
    有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
    #1、admin: 从身份认证的角度讲,这是“root”数据库,如果将一个用户添加到admin数据库,这个用户将自动获得所有数据库的权限。再者,一些特定的服务器端命令也只能从admin数据库运行,如列出所有数据库或关闭服务器
    #2、local: 这个数据库永远都不可以复制,且一台服务器上的所有本地集合都可以存储在这个数据库中
    #3、config: MongoDB用于分片设置时,分片信息会存储在config数据库中
    

    4、强调:把数据库名添加到集合名前,得到集合的完全限定名,即命名空间

    例如:
    如果要使用cms数据库中的blog.posts集合,这个集合的命名空间就是
    cmd.blog.posts。命名空间的长度不得超过121个字节,且在实际使用中应该小于100个字节
    

    三. 安装

    1.安装

    #1、安装路径为D:\MongoDB,将D:\MongoDB\bin目录加入环境变量
    
    #2、新建目录与文件
    D:\MongoDB\data\db
    D:\MongoDB\log\mongod.log
    
    #3、新建配置文件mongod.cfg,参考:https://docs.mongodb.com/manual/reference/configuration-options/
    systemLog:
       destination: file
       path: "D:\MongoDB\log\mongod.log"
       logAppend: true
    storage:
       journal:
          enabled: true
       dbPath: "D:\MongoDB\data\db"
    net:
       bindIp: 0.0.0.0
       port: 27017
    setParameter:
       enableLocalhostAuthBypass: false
        
    #4、制作系统服务
    mongod --config "D:\MongoDB\mongod.cfg" --bind_ip 0.0.0.0 --install
    或者直接在命令行指定配置
    mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db  --serviceName "MongoDB" --serviceDisplayName "MongoDB"  --install
    
            
    先停掉服务:net stop MongoDB
    然后移除服务:mongo --remove
    再重新制作服务,需要加上--auth,表示加载认证功能
    mongod --bind_ip 0.0.0.0 --port 27017 --logpath D:\MongoDB\log\mongod.log --logappend --dbpath D:\MongoDB\data\db  --serviceName "MongoDB" --serviceDisplayName "MongoDB"  --install --auth       
            
    
    
    #5、启动\关闭
    net start MongoDB
    net stop MongoDB
    
    #6、登录
    mongo
    
    链接:http://www.runoob.com/mongodb/mongodb-window-install.html
    

    2. 账号管理

    
    #1、创建账号
    use admin
    db.createUser(
      {
        user: "root",
        pwd: "123",
        roles: [ { role: "root", db: "admin" } ]
      }
    )
    
    use test
    db.createUser(
      {
        user: "tom",
        pwd: "123",
        roles: [ { role: "readWrite", db: "test" },
                 { role: "read", db: "db1" } ]
      }
    )
    
    
    #2、重启数据库
    mongod --remove
    mongod --config "C:\mongodb\mongod.cfg" --bind_ip 0.0.0.0 --install --auth
    
    #3、登录:注意使用双引号而非单引号
    mongo --port 27017 -u "root" -p "123" --authenticationDatabase "admin"
    
    也可以在登录之后用db.auth("账号","密码")登录
    mongo
    use admin
    db.auth("root","123")
    
    #推荐博客:https://www.cnblogs.com/zhoujinyi/p/4610050.html
    

    3. 命令行shell

    #1、mongo 127.0.0.1:27017/config #连接到任何数据库config
    
    #2、mongo --nodb #不连接到任何数据库
    
    #3、启动之后,在需要时运行new Mongo(hostname)命令就可以连接到想要的mongod了:
    > conn=new Mongo('127.0.0.1:27017')
    connection to 127.0.0.1:27017
    > db=conn.getDB('admin')
    admin
    
    #4、help查看帮助
    
    #5、mongo时一个简化的JavaScript shell,是可以执行JavaScript脚本的
    

    4."_id"与ObjectId

    MongoDB中存储的文档必须有一个"_id"键。这个键的值可以是任意类型,默认是个ObjectId对象。
    在一个集合里,每个文档都有唯一的“_id”,确保集合里每个文档都能被唯一标识。
    不同集合"_id"的值可以重复,但同一集合内"_id"的值必须唯一
    
    #1、ObjectId
    ObjectId是"_id"的默认类型。因为设计MongoDb的初衷就是用作分布式数据库,所以能够在分片环境中生成
    唯一的标识符非常重要,而常规的做法:在多个服务器上同步自动增加主键既费时又费力,这就是MongoDB采用
    ObjectId的原因。
    ObjectId采用12字节的存储空间,是一个由24个十六进制数字组成的字符串
        0|1|2|3|   4|5|6|     7|8    9|10|11    
        时间戳      机器      PID    计数器
    如果快速创建多个ObjectId,会发现每次只有最后几位有变化。另外,中间的几位数字也会变化(要是在创建过程中停顿几秒)。
    这是ObjectId的创建方式导致的,如上图
    
    时间戳单位为秒,与随后5个字节组合起来,提供了秒级的唯一性。这个4个字节隐藏了文档的创建时间,绝大多数驱动程序都会提供
    一个方法,用于从ObjectId中获取这些信息。
    
    因为使用的是当前时间,很多用户担心要对服务器进行时钟同步。其实没必要,因为时间戳的实际值并不重要,只要它总是不停增加就好。
    接下来3个字节是所在主机的唯一标识符。通常是机器主机名的散列值。这样就可以保证不同主机生成不同的ObjectId,不产生冲突
    
    接下来连个字节确保了在同一台机器上并发的多个进程产生的ObjectId是唯一的
    
    前9个字节确保了同一秒钟不同机器不同进程产生的ObjectId是唯一的。最后3个字节是一个自动增加的 计数器。确保相同进程的同一秒产生的
    ObjectId也是不一样的。
    
    #2、自动生成_id
    如果插入文档时没有"_id"键,系统会自帮你创建 一个。可以由MongoDb服务器来做这件事。
    但通常会在客户端由驱动程序完成。这一做法非常好地体现了MongoDb的哲学:能交给客户端驱动程序来做的事情就不要交给服务器来做。
    这种理念背后的原因是:即便是像MongoDB这样扩展性非常好的数据库,扩展应用层也要比扩展数据库层容易的多。将工作交给客户端做就
    减轻了数据库扩展的负担。
    

    5.MangoDB基本数据类型

    #1、null:用于表示空或不存在的字段
    d={'x':null}
    #2、布尔型:true和false
    d={'x':true,'y':false}
    #3、数值
    d={'x':3,'y':3.1415926}
    #4、字符串
    d={'x':'tom'}
    #5、日期
    d={'x':new Date()}
    d.x.getHours()
    #6、正则表达式
    d={'pattern':/^egon.*?nb$/i}
    
    正则写在//内,后面的i代表:
    i 忽略大小写
    m 多行匹配模式
    x 忽略非转义的空白字符
    s 单行匹配模式
    
    #7、数组
    d={'x':[1,'a','v']}
    
    #8、内嵌文档
    user={'name':'tom','addr':{'country':'China','city':'YT'}}
    user.addr.country
    
    #9、对象id:是一个12字节的ID,是文档的唯一标识,不可变
    d={'x':ObjectId()}
    

    四. CRUD操作

    1、数据库操作

    #1、增
    use db1 #如果数据库不存在,则创建数据库,否则切换到指定数据库。
    
    #2、查
    show dbs #查看所有
    可以看到,我们刚创建的数据库db1并不在数据库的列表中, 要显示它,我们需要向db1数据库插入一些数据。
    db.table1.insert({'a':1})
    
    #3、删
    use db1 #先切换到要删的库下
    db.dropDatabase() #删除当前库
    

    2、集合操作

    #1、增
    当第一个文档插入时,集合就会被创建
    > use database1
    switched to db database1
    > db.table1.insert({'a':1})
    WriteResult({ "nInserted" : 1 })
    > db.table2.insert({'b':2})
    WriteResult({ "nInserted" : 1 })
    
    db.user
    db.user.info	表名是user.info,跟user表没有任何关系
    db.user.auth
    
    
    
    #2、查
    > show tables
    table1
    table2
    
    #3、删
    > db.table1.drop()
    true
    > show tables
    table2
    

    3、文档操作

    #1、没有指定_id则默认ObjectId,_id不能重复,且在插入后不可变
    
    #2、插入单条
    user0={
        "name":"tom",
        "age":10,
        'hobbies':['music','read','dancing'],
        'addr':{
            'country':'China',
            'city':'BJ'
        }
    }
    
    db.test.insert(user0)
    db.test.find()
    
    #3、插入多条
    user1={
        "_id":1,
        "name":"zhang3",
        "age":10,
        'hobbies':['music','read','dancing'],
        'addr':{
            'country':'China',
            'city':'weifang'
        }
    }
    
    user2={
        "_id":2,
        "name":"li4",
        "age":20,
        'hobbies':['music','read','run'],
        'addr':{
            'country':'China',
            'city':'hebei'
        }
    }
    
    
    user3={
        "_id":3,
        "name":"wang5",
        "age":30,
        'hobbies':['music','drink'],
        'addr':{
            'country':'China',
            'city':'heibei'
        }
    }
    
    user4={
        "_id":4,
        "name":"zhao6",
        "age":40,
        'hobbies':['music','read','dancing','tea'],
        'addr':{
            'country':'China',
            'city':'BJ'
        }
    }
    
    user5={
        "_id":5,
        "name":"sun7",
        "age":50,
        'hobbies':['music','read',],
        'addr':{
            'country':'China',
            'city':'henan'
        }
    }
    db.user.insertMany([user1,user2,user3,user4,user5])
    
    
    db.t1.insert({"_id":1,"a":"1","b":"2","c":"3"})
    db.t1.save({"_id":1,"z":"6"})   有就用新的记录覆盖掉原来的记录,无就新增
    
    • 比较运算
    # SQL:=,!=,>,<,>=,<=
    # MongoDB:{key:value}代表什么等于什么
    "$ne"====>不等于
    "$gt"====>大于
    "$lt"====>小于
    "gte"====>大于等于
    "lte"====>小于等于
    其中"$ne"能用于所有数据类型
    
    #1、select * from db1.user where name = "alex";
    db.user.find({'name':'alex'})
    
    #2、select * from db1.user where name != "alex";
    db.user.find({'name':{"$ne":'alex'}})
    
    #3、select * from db1.user where id > 2;
    db.user.find({'_id':{'$gt':2}})
    
    #4、select * from db1.user where id < 3;
    db.user.find({'_id':{'$lt':3}})
    
    #5、select * from db1.user where id >= 2;
    db.user.find({"_id":{"$gte":2,}})
    
    #6、select * from db1.user where id <= 2;
    db.user.find({"_id":{"$lte":2}})
    
    • 逻辑运算
    # SQL:and,or,not
    # MongoDB:字典中逗号分隔的多个条件是and关系,"$or"的条件放到[]内,"$not"
    
    #1、select * from db1.user where id >= 2 and id < 4;
    db.user.find({'_id':{"$gte":2,"$lt":4}})
    
    #2、select * from db1.user where id >= 2 and age < 40;
    db.user.find({"_id":{"$gte":2},"age":{"$lt":40}})
    
    #3、select * from db1.user where id >= 5 or name = "alex";
    db.user.find({
        "$or":[
            {'_id':{"$gte":5}},
            {"name":"alex"}
            ]
    })
    
    #4、select * from db1.user where id % 2=1;
    db.user.find({'_id':{"$mod":[2,1]}})
    
    #5、上题,取反
    db.user.find({'_id':{"$not":{"$mod":[2,1]}}})
    
    • 成员运算
    # SQL:in,not in
    # MongoDB:"$in","$nin"
    
    #1、select * from db1.user where age in (20,30,31);
    db.user.find({"age":{"$in":[20,30,31]}})
    
    #2、select * from db1.user where name not in ('alex','yuanhao');
    db.user.find({"name":{"$nin":['alex','yuanhao']}})
    
    • 正则匹配
    # SQL: regexp 正则
    # MongoDB: /正则表达/i
    
    #1、select * from db1.user where name regexp '^j.*?(g|n)$';
    db.user.find({'name':/^j.*?(g|n)$/i})
    
    • 去指定的字段
    #1、select name,age from db1.user where id=3;
    db.user.find({'_id':3},{'_id':0,'name':1,'age':1})
    1:代表要,类似True
    0:代表不要,类似Flase,默认是0
    
    • 查询数组
    #1、查看有dancing爱好的人
    db.user.find({'hobbies':'dancing'})
    
    #2、查看既有dancing爱好又有tea爱好的人
    db.user.find({
        'hobbies':{
            "$all":['dancing','tea']
            }
    })
    
    #3、查看第4个爱好为tea的人:".方法"
    db.user.find({"hobbies.3":'tea'})
    
    #4、查看所有人最后两个爱好:"$slice"
    db.user.find({},{'hobbies':{"$slice":-2},"age":0,"_id":0,"name":0,"addr":0})
    
    #5、查看所有人的第2个到第3个爱好
    db.user.find({},{'hobbies':{"$slice":[1,2]},"age":0,"_id":0,"name":0,"addr":0})
    
    > db.blog.find().pretty()
    {
            "_id" : 1,
            "name" : "sun7公司破产的真相",
            "comments" : [
                    {
                            "name" : "zhang3",
                            "content" : "sun7是谁???",
                            "thumb" : 200
                    },
                    {
                            "name" : "li4",
                            "content" : "我去,真的假的",
                            "thumb" : 300
                    },
                    {
                            "name" : "wang5",
                            "content" : "吃喝嫖赌抽,欠下两个亿",
                            "thumb" : 40
                    },
                    {
                            "name" : "zhao6",
                            "content" : "丐帮欢迎你",
                            "thumb" : 0
                    }
            ]
    }
    db.blog.find({},{'comments':{"$slice":-2}}).pretty() #查询最后两个
    db.blog.find({},{'comments':{"$slice":[1,2]}}).pretty() #查询1到2
    
    • 排序
    # 排序:1代表升序,-1代表降序
    db.user.find().sort({"name":1})
    db.user.find().sort({"age":-1,'_id':1})
    
    • 分页
    # 分页:limit代表取多少个document,skip代表跳过前多少个document。 
    db.user.find().sort({'age':1}).limit(1).skip(2)
    
    • 获取数量
    # 获取数量
    db.user.count({'age':{"$gt":30}}) 
    
    --或者
    db.user.find({'age':{"$gt":30}}).count()
    
    • 其他
    #1、{'key':null} 匹配key的值为null或者没有这个key
    db.t2.insert({'a':10,'b':111})
    db.t2.insert({'a':20})
    db.t2.insert({'b':null})
    
    > db.t2.find({"b":null})
    { "_id" : ObjectId("5a5cc2a7c1b4645aad959e5a"), "a" : 20 }
    { "_id" : ObjectId("5a5cc2a8c1b4645aad959e5b"), "b" : null }
    
    #2、查找所有
    db.user.find() #等同于db.user.find({})
    db.user.find().pretty()
    
    #3、查找一个,与find用法一致,只是只取匹配成功的第一个
    db.user.findOne({"_id":{"$gt":3}})
    
    #4、去重
    db.user.find().distinct()
    
    • update语法介绍
    update() 方法用于更新已存在的文档。语法格式如下:
    db.collection.update(
       <query>,
       <update>,
       {
         upsert: <boolean>,
         multi: <boolean>,
         writeConcern: <document>
       }
    )
    参数说明:对比update db1.t1 set name='zhangsan',sex='Male' where name='zhang3' and age=18;
    
    query : 相当于where条件。
    update : update的对象和一些更新的操作符(如$,$inc...等,相当于set后面的
    upsert : 可选,默认为false,代表如果不存在update的记录不更新也不插入,设置为true代表插入。
    multi : 可选,默认为false,代表只更新找到的第一条记录,设为true,代表更新找到的全部记录。
    writeConcern :可选,抛出异常的级别。
    
    更新操作是不可分割的:若两个更新同时发送,先到达服务器的先执行,然后执行另外一个,不会破坏文档。
    
    
    • 覆盖式
    #注意:除非是删除,否则_id是始终不会变的
    #1、覆盖式:
    db.user.update({'age':20},{"name":"wang5","hobbies_count":3})
    是用{"_id":2,"name":"wang5","hobbies_count":3}覆盖原来的记录
    
    #2、一种最简单的更新就是用一个新的文档完全替换匹配的文档。这适用于大规模式迁移的情况。例如
    var obj=db.user.findOne({"_id":2})
    
    obj.username=obj.name+'SB'
    obj.hobbies_count++
    delete obj.age
    
    db.user.update({"_id":2},obj)
    
    • 设置:$set
    #设置:$set
    
    通常文档只会有一部分需要更新。可以使用原子性的更新修改器,指定对文档中的某些字段进行更新。
    更新修改器是种特殊的键,用来指定复杂的更新操作,比如修改、增加后者删除
    
    #1、update db1.user set  name="wang5" where id = 2
    db.user.update({'_id':2},{"$set":{"name":"wang5",}})
    
    #2、没有匹配成功则新增一条{"upsert":true}
    db.user.update({'_id':6},{"$set":{"name":"wang5","age":18}},{"upsert":true})
    
    #3、默认只改匹配成功的第一条,{"multi":改多条}
    db.user.update({'_id':{"$gt":4}},{"$set":{"age":28}})
    db.user.update({'_id':{"$gt":4}},{"$set":{"age":38}},{"multi":true})
    
    #4、修改内嵌文档,把名字为wang5的人所在的地址国家改成Japan
    db.user.update({'name':"wang5"},{"$set":{"addr.country":"Japan"}})
    
    #5、把名字为wang5的人的地2个爱好改成piao
    db.user.update({'name':"wang5"},{"$set":{"hobbies.1":"piao"}})
    
    #6、删除wang5的爱好,$unset
    db.user.update({'name':"wang5"},{"$unset":{"hobbies":""}})
    
    • 增加和减少:$inc
    #增加和减少:$inc
    
    #1、所有人年龄增加一岁
    db.user.update({},
        {
            "$inc":{"age":1}
        },
        {
            "multi":true
        }
        )
    #2、所有人年龄减少5岁
    db.user.update({},
        {
            "$inc":{"age":-5}
        },
        {
            "multi":true
        }
        )
    
    • 添加删除数组内元素:push,push,pop,$pull
    #添加删除数组内元素
        
    往数组内添加元素:$push
    #1、为名字为wang5的人添加一个爱好read
    db.user.update({"name":"wang5"},{"$push":{"hobbies":"read"}})
    
    #2、为名字为wang5的人一次添加多个爱好tea,dancing
    db.user.update({"name":"wang5"},{"$push":{
        "hobbies":{"$each":["tea","dancing"]}
    }})
    
    按照位置且只能从开头或结尾删除元素:$pop
    #3、{"$pop":{"key":1}} 从数组末尾删除一个元素
    
    db.user.update({"name":"wang5"},{"$pop":{
        "hobbies":1}
    })
    
    #4、{"$pop":{"key":-1}} 从头部删除
    db.user.update({"name":"wang5"},{"$pop":{
        "hobbies":-1}
    })
    
    #5、按照条件删除元素,:"$pull" 把符合条件的统统删掉,而$pop只能从两端删
    db.user.update({'addr.country':"China"},{"$pull":{
        "hobbies":"read"}
    },
    {
        "multi":true
    }
    )
    
    • 避免添加重复:"$addToSet"
    #避免添加重复:"$addToSet"
    
    db.urls.insert({"_id":1,"urls":[]})
    
    db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
    db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
    db.urls.update({"_id":1},{"$addToSet":{"urls":'http://www.baidu.com'}})
    
    db.urls.update({"_id":1},{
        "$addToSet":{
            "urls":{
            "$each":[
                'http://www.baidu.com',
                'http://www.baidu.com',
                'http://www.xxxx.com'
                ]
                }
            }
        }
    )
    
    • 其他
    #1、了解:限制大小"$slice",只留最后n个
    
    db.user.update({"_id":5},{
        "$push":{"hobbies":{
            "$each":["read",'music','dancing'],
            "$slice":-2
        }
        }
    })
    
    #2、了解:排序The $sort element value must be either 1 or -1"
    db.user.update({"_id":5},{
        "$push":{"hobbies":{
            "$each":["read",'music','dancing'],
            "$slice":-1,
            "$sort":-1
        }
        }
    })
    
    #注意:不能只将"$slice"或者"$sort"与"$push"配合使用,且必须使用"$eah"
    
    #1、删除多个中的第一个
    db.user.deleteOne({ 'age': 8 })
    
    #2、删除国家为China的全部
    db.user.deleteMany( {'addr.country': 'China'} ) 
    
    #3、删除全部
    db.user.deleteMany({})
    
    聚合
    如果你有数据存储在MongoDB中,你想做的可能就不仅仅是将数据提取出来那么简单了;你可能希望对数据进行分析并加以利用。MongoDB提供了以下聚合工具:
    #1、聚合框架
    #2、MapReduce(详见MongoDB权威指南)
    #3、几个简单聚合命令:count、distinct和group。(详见MongoDB权威指南)
    
    #聚合框架:
    可以使用多个构件创建一个管道,上一个构件的结果传给下一个构件。
    这些构件包括(括号内为构件对应的操作符):筛选($match)、投射($project)、分组($group)、排序($sort)、限制($limit)、跳过($skip)
    不同的管道操作符可以任意组合,重复使用
    
    • 准备数据
    from pymongo import MongoClient
    import datetime
    
    client=MongoClient('mongodb://root:123@localhost:27017')
    table=client['db1']['emp']
    # table.drop()
    
    l=[
    ('tom','male',18,'20170301','校长',73000.33,401,1), #以下是教学部
    ('bob','male',78,'20150302','teacher',10000.31,401,1),
    ('sam','male',81,'20130305','teacher',8300,401,1),
    ('zhang3','male',73,'20140701','teacher',3500,401,1),
    ('li4','male',28,'20121101','teacher',2100,401,1),
    ('may','female',18,'20110211','teacher',9000,401,1),
    ('wang5','male',18,'19000301','teacher',30000,401,1),
    ('成龙','male',48,'20101111','teacher',10000,401,1),
    
    ('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
    ('丫丫','female',38,'20101101','sale',2000.35,402,2),
    ('丁丁','female',18,'20110312','sale',1000.37,402,2),
    ('星星','female',18,'20160513','sale',3000.29,402,2),
    ('格格','female',28,'20170127','sale',4000.33,402,2),
    
    ('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
    ('程咬金','male',18,'19970312','operation',20000,403,3),
    ('程咬银','female',18,'20130311','operation',19000,403,3),
    ('程咬铜','male',18,'20150411','operation',18000,403,3),
    ('程咬铁','female',18,'20140512','operation',17000,403,3)
    ]
    
    for n,item in enumerate(l):
        d={
            "_id":n,
            'name':item[0],
            'sex':item[1],
            'age':item[2],
            'hire_date':datetime.datetime.strptime(item[3],'%Y%m%d'),
            'post':item[4],
            'salary':item[5]
        }
        table.save(d)
    
    • 筛选:$match
    {"$match":{"字段":"条件"}},可以使用任何常用查询操作符$gt,$lt,$in#例1、select * from db1.emp where post='teacher';
    db.emp.aggregate({"$match":{"post":"teacher"}})
    
    #例2、select * from db1.emp where id > 3 group by post;  
    db.emp.aggregate(
        {"$match":{"_id":{"$gt":3}}},
        {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}}
    )
    
    #例3、select * from db1.emp where id > 3 group by post having avg(salary) > 10000;  
    db.emp.aggregate(
        {"$match":{"_id":{"$gt":3}}},
        {"$group":{"_id":"$post",'avg_salary':{"$avg":"$salary"}}},
        {"$match":{"avg_salary":{"$gt":10000}}}
    )
    
    • 投射:$project
    {"$project":{"要保留的字段名":1,"要去掉的字段名":0,"新增的字段名":"表达式"}}
    
    #1、select name,post,(age+1) as new_age from db1.emp;
    db.emp.aggregate(
        {"$project":{
            "name":1,
            "post":1,
            "new_age":{"$add":["$age",1]}
            }
    })
    
    #2、表达式之数学表达式
    {"$add":[expr1,expr2,...,exprN]} #相加
    {"$subtract":[expr1,expr2]} #第一个减第二个
    {"$multiply":[expr1,expr2,...,exprN]} #相乘
    {"$divide":[expr1,expr2]} #第一个表达式除以第二个表达式的商作为结果
    {"$mod":[expr1,expr2]} #第一个表达式除以第二个表达式得到的余数作为结果
    
    #3、表达式之日期表达式:$year,$month,$week,$dayOfMonth,$dayOfWeek,$dayOfYear,$hour,$minute,$second
    #例如:select name,date_format("%Y") as hire_year from db1.emp
    db.emp.aggregate(
        {"$project":{"name":1,"hire_year":{"$year":"$hire_date"}}}
    )
    
    #例如查看每个员工的工作多长时间
    db.emp.aggregate(
        {"$project":{"name":1,"hire_period":{
            "$subtract":[
                {"$year":new Date()},
                {"$year":"$hire_date"}
            ]
        }}}
    )
    
    
    #4、字符串表达式
    {"$substr":[字符串/$值为字符串的字段名,起始位置,截取几个字节]}
    {"$concat":[expr1,expr2,...,exprN]} #指定的表达式或字符串连接在一起返回,只支持字符串拼接
    {"$toLower":expr}
    {"$toUpper":expr}
    
    db.emp.aggregate( {"$project":{"NAME":{"$toUpper":"$name"}}})
    
    #5、逻辑表达式
    $and
    $or
    $not
    其他见Mongodb权威指南
    
    
    
    • 分组:$group
    {"$group":{"_id":分组字段,"新的字段名":聚合操作符}}
    
    #1、将分组字段传给$group函数的_id字段即可
    {"$group":{"_id":"$sex"}} #按照性别分组
    {"$group":{"_id":"$post"}} #按照职位分组
    {"$group":{"_id":{"state":"$state","city":"$city"}}} #按照多个字段分组,比如按照州市分组
    
    #2、分组后聚合得结果,类似于sql中聚合函数的聚合操作符:$sum、$avg、$max、$min、$first、$last
    #例1:select post,max(salary) from db1.emp group by post; 
    db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"}}})
    
    #例2:去每个部门最大薪资与最低薪资
    db.emp.aggregate({"$group":{"_id":"$post","max_salary":{"$max":"$salary"},"min_salary":{"$min":"$salary"}}})
    
    #例3:如果字段是排序后的,那么$first,$last会很有用,比用$max和$min效率高
    db.emp.aggregate({"$group":{"_id":"$post","first_id":{"$first":"$_id"}}})
    
    #例4:求每个部门的总工资
    db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":"$salary"}}})
    
    #例5:求每个部门的人数
    db.emp.aggregate({"$group":{"_id":"$post","count":{"$sum":1}}})
    
    #3、数组操作符
    {"$addToSet":expr}:不重复
    {"$push":expr}:重复
    
    #例:查询岗位名以及各岗位内的员工姓名:select post,group_concat(name) from db1.emp group by post;
    db.emp.aggregate({"$group":{"_id":"$post","names":{"$push":"$name"}}})
    db.emp.aggregate({"$group":{"_id":"$post","names":{"$addToSet":"$name"}}})
    
    
    
    • 排序:sortsort、限制:limit、跳过:$skip
    {"$sort":{"字段名":1,"字段名":-1}} #1升序,-1降序
    {"$limit":n} 
    {"$skip":n} #跳过多少个文档
    
    #例1、取平均工资最高的前两个部门
    db.emp.aggregate(
    {
        "$group":{"_id":"$post","平均工资":{"$avg":"$salary"}}
    },
    {
        "$sort":{"平均工资":-1}
    },
    {
        "$limit":2
    }
    )
    #例2、
    db.emp.aggregate(
    {
        "$group":{"_id":"$post","平均工资":{"$avg":"$salary"}}
    },
    {
        "$sort":{"平均工资":-1}
    },
    {
        "$limit":2
    },
    {
        "$skip":1
    }
    )
    
    • 随机选取n个:$sample
    #集合users包含的文档如下
    { "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }
    { "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false  }
    { "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true  }
    { "_id" : 4, "name" : "li", "q1" : true, "q2" : false  }
    { "_id" : 5, "name" : "annT", "q1" : false, "q2" : true  }
    { "_id" : 6, "name" : "li", "q1" : true, "q2" : true  }
    { "_id" : 7, "name" : "ty", "q1" : false, "q2" : true  }
    
    #下述操作时从users集合中随机选取3个文档
    db.users.aggregate(
       [ { $sample: { size: 3 } } ]
    )
    
    展开全文
  • MongoDB实战之---初级篇

    万人学习 2018-11-27 10:25:02
    本课程环境:MongoDB 3.4.x CentOS 7.x 本课程为初级课程,围绕高阶聚合函数的使用、索引的介绍及原理解析、索引优化、性能优化、副本集搭建及分布式分片集群的搭建和原理解析来对MongoDB进行更深入的学习。 本...
  • MongoDB基础篇:MongoDB Shell命令大全

    万次阅读 2019-07-29 18:41:12
    要想能熟练操作MongoDB,首先先要熟练使用 MongoDB Shell, 再次要熟练使用驱动 mongodb-java-driver, 最后是spring-data-mongodb的使用 在使用Shell中的方法时,注意很多方法都是有重载函数的一:启动服务和连接...
    分享一个朋友的人工智能教程。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。

    要想能熟练操作MongoDB,首先先要熟练使用 MongoDB Shell, 再次要熟练使用驱动 mongodb-java-driver, 最后是spring-data-mongodb的使用

    MongoDB 简介:

    MongoDB采用Bson格式存储,BSON格式比JSON数据类型更加丰富,
    支持ObjectId、日期类型、正则表达式、JS代码、二进制数据等

    MongoDB注意:

    • MongoDB 不支持事务
    • MongoDB 不支持多表连接查询
    • MongoDB 中的键值对是有序的,相同的键值对,不同的顺序,属于不同的文档
    • new Date(); 返回日期对象,属于日期类型,Date()函数返回日期字符串,在Shell中操作日期要使用日期类型, 日期类型是包含时区的
    • _id的值可以是任意类型,默认是ObjectId类型,可以在分片环境中生成唯一的标识符(时间戳(单位:秒)+主机的唯一标示(主机名的hash值)+进程标识符PID+自动增加的计数器), 通过时间戳可以大概知道ObjectId大概是按时间先后排序的,主机的唯一标示可以用于保证在多台服务器器上不重复,进程ID为了保证同台服务器器上多个不同的进程之间生成不重复 值,最后一部分是一个自增的计数器, 前面三部分是为了保证同一秒在同一台机器上的同一个进程上生成一个唯一的值,最后一部分用于保证在同一秒、同一台机器、同一个进程 在同一秒内(注意是同一秒内)生成唯一值
    • mongodb中有一些特殊的键,它们被称为修改器、操作符等
    以 $ 开头,如 
    $set(更新字段)、
    $unset(删除字段)、 
    $inc(自增或自减)、
    $and、$or、$in、$nin、$nor、$exists(用于判断文档中是否包含某字段)、
    $push(向数组中尾部添加一个元素)、
    $pushAll(将数组中的所有值push)、
    $addToSet(向set集合中添加元素)、
    $pop(删除数组中的头部或尾部元素), 
    $pull(删除数组中指定的值)、
    $size(根据数组的长度进行筛选)、
    $slice(返回数组中部分元素,如前几个、后几个、中间连续几个元素)、
    $elemMatch(用于匹配数组中的多个条件)、
    $where(自定义筛选条件,效率比较低,需要将bson转为js对象,不能使用索引,可以先使用普通查询过滤掉部分不满足条件的文档,然后再使用where,尽量减少where操作文档的数量过大)
    
    

    MongoDB 与 关系型数据库的对比:

    • MongoDB ----------> SQL
    • database数据库 ---->database数据库
    • collection集合------->table表
    • document文档----> row 行
    • filed字段-------> column列
    • index索引-----> index索引
    • 不支持多表连接查询—> 支持多表连接查询
      在使用Shell中的方法时,注意很多方法都是有重载函数的

    一:启动服务和连接服务

    1、mongod 用于启动MongoDB服务

    MongoDB的数据时存储在磁盘上的,而不是存储在内存中的,所以在启动MongoDB服务时需要指定数据存储的位置, 如果不指定会默认存储在/data/db目录下, 注意在使用默认位置时,需要以管理员身份预先创建好目录

    方式一: 使用默认的路径,MongoDB安装所在的盘符:/data/db

    C:\Windows\system32>D:
    D:\>mkdir data
    D:\>cd data
    D:\data>mkdir db
    D:\data>cd D:\Java\MongoDB\Server\bin
    D:\Java\MongoDB\Server\bin>mongod
    
    MongoDB starting : pid=9712 port=27017 dbpath=D:\data\db\ 64-bit host=zm-PC
    

    这里写图片描述

    方式二: 显式指定数据库路径

    此种方式也要预先创建好目录,这里的位置放置MongoDB里面,如D:\Java\MongoDB\DB,放在MongoDB里面不需要管理员身份创建
    这里写图片描述

    方式三: 安装服务

    D:\Java\MongoDB\Server\bin>mongod  --dbpath=D:\data\db --logappend --logpath=D:\data\log.txt --install
    

    这里写图片描述

    以后启动服务只需要net start MongoDB, 比mongod --dbpath=xxx稍微方便些, 以后电脑开机后就自动启动了,省的每次都要启动

    这里写图片描述


    2、mongo 用于客户端连接服务器

    语法: mongo [IP:PORT][/DATABASE_NAME]

    IP默认的是127.0.0.1
    Port默认的是27017
    database默认的是test,mongodb中默认有两个数据库admin、local

    D:\Java\MongoDB\Server\bin>mongo
    

    这里写图片描述

    D:\Java\MongoDB\Server\bin>mongo 127.0.0.1:27017
    
    D:\Java\MongoDB\Server\bin>mongo 127.0.0.1:27017/admin
    
    // 连接时不指定要连接数据库,需要时从连接中获取需要的数据库
    D:\Java\MongoDB\Server\bin>mongo --nodb
    MongoDB shell version v3.4.6
    > db
    2017-07-27T20:27:25.181+0800 E QUERY    [thread1] ReferenceError: db is not defined :
    @(shell):1:1
    > conn = new Mongo("localhost:27017")
    connection to localhost:27017
    > db = conn.getDB("test")
    test
    >
    

    3. 基本命令

    help命令:如果想知道某个对象下都有哪些函数可以使用help命令,直接使用help会列举出mongodb支持操作,使用db.help()会列举所有db对象所支持的所有操作,使用db.mycoll.help()可以列举所有集合对象对应的操作

    > help
            db.help()                    help on db methods
            db.mycoll.help()             help on collection methods
            sh.help()                    sharding helpers
            rs.help()                    replica set helpers
            help admin                   administrative help
            help connect                 connecting to a db help
            help keys                    key shortcuts
            help misc                    misc things to know
            help mr                      mapreduce
    
            show dbs                     show database names
            show collections             show collections in current database
            show users                   show users in current database
            show profile                 show most recent system.profile entries with time >= 1ms
            show logs                    show the accessible logger names
            show log [name]              prints out the last segment of log in memory, 'global' is default
            use <db_name>                set current database
            db.foo.find()                list objects in collection foo
            db.foo.find( { a : 1 } )     list objects in foo where a == 1
            it                           result of the last line evaluated; use to further iterate
            DBQuery.shellBatchSize = x   set default number of items to display on shell
            exit                         quit the mongo shell
    // 查看所有数据级别的操作
    > db.help()
    // 查看集合级别的操作
    > db.mycoll.help()
    // 列举数据库命令
    > db.listCommands()
    

    查看函数方法的实现或者查看方法的定义(比如忘记函数的参数了)可以通过输入函数名,不带小括号

    > db.foo.update
    function (query, obj, upsert, multi) {
        var parsed = this._parseUpdate(query, obj, upsert, multi);
        ...
    }
    
    // 打印语句
    > print("hello, mongodb")
    hello, mongodb
    >
    
    // 执行js脚本
    D:\Java\MongoDB\Server\bin>mongo script1.js script2.js
    loading file: script1.js
    I am script1.js
    loading file: script2.js
    I am script2.js
    
    // 使用load()函数加载脚本来执行
    > load("script1.js")
    I am script1.js
    true
    
    // script3.js
    print(db.getMongo().getDBs());	  // show dbs
    db.getSisterDB("foo");    // use foo
    db.users.insert({"username": "mengday", "age": 26})
    print(db.getCollectionNames());  // show collections
    
    > load("script3.js")
    [object BSON]
    users
    true
    >
    
    // 使用脚本可以定义一些辅助的工具函数
    tools.js
    var connectTo = function (port, dbname) {
    	if(!port) port = 27017;
    	if(!dbname) dbname = "test";
    
    	db = connect("localhost:" + port + "/" + dbname);
    
    	return db;
    }
    
    > load("tools.js")
    true
    > typeof connectTo
    function
    > connectTo("27017", "admin")
    connecting to: mongodb://localhost:27017/admin
    MongoDB server version: 3.4.6
    admin
    >
    
    客户端启动时自动执行js脚本
    在用户的主目录下(如C:\Users\mengday)下创建一个.mongorc.js文件,该脚本可以做一些操作,如重写shell命令,禁掉一部分功能,如删除数据库,表等危险操作
    // .mongorc.js
    print("--------------MongoDB is started--------------");
    
    var no = function(){
    	print("not permission");
    }
    
    db.dropDatabase = DB.prototype.dropDatabase = no;
    DBCollection.prototype = no;
    DBCollection.prototype.dropIndex = no;
    
    // 启动shell时会自动执行
    D:\Java\MongoDB\Server\bin>mongo
    MongoDB shell version v3.4.6
    connecting to: mongodb://127.0.0.1:27017
    MongoDB server version: 3.4.6
    ----------------MongoDB is started-----------------
    > db
    test
    > db.dropDatabase()
    not permission
    >
    
    // mongo 启动后给EDITOR变量赋值一个文本编辑器的位置,然后就可以使用edit命令来打开编辑某个变量了,编辑后保存,然后直接关掉编辑器即可,这对于一条命令或者变量比较长编辑比较方便,注意文本编辑器的位置不能包含空格,路径要使用/,不能使用\
    EDITOR="D:/SublimeText/sublime_text.exe"
    var user = {"username": "mengday", "nickname": "xxx"};
    edit user
    
    // 方式二:可以将该配置放在.mongorc.js中,以后就不用每次设置了
    EDITOR="D:/SublimeText/sublime_text.exe";
    

    二:数据库基本命令

    这里写图片描述

    查看当前数据库 db
    显示所有数据库 show dbs,如果数据库里没有任何集合,是不展示出来的,如 use test2, show dbs 时是不包含test2数据库的
    切换或者新建数据库 use DATABASE_NAME, 切换数据库时如果数据库不存在,则会创建它
    删除数据库 db.dropDatabase()
    显示所有表(集合)show tables
    查看js方法的原型(源代码实现): db.xxx.insert, 随便写一个集合名字,集合后面跟函数名,不需要函数的参数 即可查看该函数的源码实现

    // mong shell 是一种javascript shell, 可以定义变量、函数,调用函数
    > x = 200
    200
    > x / 5
    40
    > Math.sin(Math.PI / 2)
    1
    // new Date():是创建一个日期对象,而Date()函数是返回日期字符串,注意日期类型数据和字符串数据不是一种数据,MongoDB Shell在操作日期字段的时候是操作的日期类型而不是字符串类型
    > new Date()
    ISODate("2017-07-27T00:18:34.370Z")
    > Date()
    Thu Jul 27 2017 08:18:37 GMT+0800
    >
    > "Hello, World!".replace("World", "MongoDB")
    Hello, MongoDB!
    > function factorial(n) {
    ... if(n <= 1) return 1;
    ... return n * factorial(n - 1);
    ... }
    > factorial(5)
    120
    >
    
    // db 是一个全局变量,存储当前的数据名称,当切换数据库时会自动更改db的值
    > db
    test
    > show dbs
    admin  0.000GB
    local  0.000GB
    > use local
    switched to db local
    > show tables
    startup_log
    > use test
    switched to db test
    > db.dropDatabase()
    { "ok" : 1 }
    > db.xxx.insert
    
    // 查看一个bson的大小,每个文档最大不超过16M
    > var user = {"username": "mengday"}
    > Object.bsonsize(user)
    27
    

    集合操作

    创建集合

    方式一:隐式创建集合
    当向集合中的插入文档时,如果集合不存在,系统会自动创建,所以向一个不存在的集合中插入数据也就是创建了集合

    > db
    test
    > show tables
    > db.users.insert({"usernmae": "mengdee", "age": 26})
    WriteResult({ "nInserted" : 1 })
    > show tables
    users
    >
    

    方式二:显示创建集合
    db.createCollection(“集合名字”, 可选配置)
    显示创建集合可以通过一些配置创建一些特殊的集合,如固定集合

    > show tables
    users
    > db.createCollection("address")
    { "ok" : 1 }
    
    // 固定集合只能通过调用方法显式创建,固定集合可以指定集合存储数据的大小和最多允许存储的条数
    // 当固定集合文档条数达到上限时,再插入新的文档会将最老的文档删除掉,然后插入到该位置
    > db.createCollection("address", {capped: true, size: 10000, max:1000})
    { "ok" : 1 }
    > show tables
    address
    users
    >
    

    删除集合

    db.集合名字.drop()

    > db.address.drop()
    true
    

    查看集合

    show tables和show collections都可以查看当前数据下的集合

    > show tables
    address
    users
    >
    > show collections
    address
    users
    >
    

    添加数据

    
    方式一: insert: _id 会自动创建唯一索引,当id重复的时候会报错
    db.集合名字.insert({})        // 插入一条,返回值中不包含insertedIds
    db.集合名字.insert([{}, {}])  // 批量插入,返回值中不包含insertedIds
    db.集合名字.insertOne(Bson)   // 插入一条,返回值返回插入的insertedId
    db.集合名字.insertMany(Bson)  // 批量插入,返回值中包含insertedIds
    db.集合名字.findAndModify({查询条件}, "update": {需要添加或更新的字段},  "upsert": true });
    
    写入安全:
    	应答模式:插入时会返回成功或者失败
    	非应答模式:插入时没有反馈,即插入有没有成功不知道
    > var user = {"name": "mengdee", "age": 20, "address": "上海市浦东新区张江镇", "create_time": new Da
    te()}
    > db.users.insert(user)
    WriteResult({ "nInserted" : 1 })
    > db.users.find()
    { "_id" : ObjectId("5976ad21670af2aa52ea90df"), "username" : "mengdee", "age" : 26 }
    { "_id" : ObjectId("5976b395670af2aa52ea90e0"), "name" : "mengdee", "age" : 20, "address" : "上海市
    浦东新区张江镇", "create_time" : ISODate("2017-07-25T02:57:04.545Z") }
    
    > var userDoc = db.users.findOne()
    > var insertDate = userDoc["_id"]
    > insertDate.getTimestamp()
    ISODate("2017-07-25T02:29:53Z")
    > insertDate.str
    5976ad21670af2aa52ea90df
    
    > db.users.insertOne({"username": "mengday3"})
    {
            "acknowledged" : true,
            "insertedId" : ObjectId("5976b632670af2aa52ea90e1")
    }
    > db.users.insertMany([{"username": "mengday4"}, {"username": "mengday5"}])
    {
            "acknowledged" : true,
            "insertedIds" : [
                    ObjectId("5976b666670af2aa52ea90e2"),
                    ObjectId("5976b666670af2aa52ea90e3")
            ]
    }
    > db.users.insert([{"username": "mengday6"}, {"username": "mengday7"}])
    BulkWriteResult({
            "writeErrors" : [ ],
            "writeConcernErrors" : [ ],
            "nInserted" : 2,
            "nUpserted" : 0,
            "nMatched" : 0,
            "nModified" : 0,
            "nRemoved" : 0,
            "upserted" : [ ]
    })
    
    // 使用insertOne插入重复的_id 会报错
    > db.users.insertOne({"_id": 1, "username": "mengday8"})
    { "acknowledged" : true, "insertedId" : 1 }
    > db.users.insertOne({"_id": 1, "username": "mengday8"})
    2017-07-25T11:15:47.822+0800 E QUERY    [thread1] WriteError: E11000 duplicate key error collection:
     test.users index: _id_ dup key: { : 1.0 } :
    WriteError({
            "index" : 0,
            "code" : 11000,
            "errmsg" : "E11000 duplicate key error collection: test.users index: _id_ dup key: { : 1.0 }
    ",
            "op" : {
                    "_id" : 1,
                    "username" : "mengday8"
            }
    })
    
    // findAndModify 也可以用于插入文档,但是前提是一定不存在,如果存在了就变成更新了,单纯的插入还是不要用种方式了,findAndModify一般用于更新或删除操作
    > db.users.findAndModify({ "query": {"username": "mengday11"}, "update": {"username": "mengday11", "age": 26},  "upsert": true })
    null
    > db.users.find()
    { "_id" : ObjectId("597c584448c373e228a9259e"), "username" : "xxx", "age" : 26 }
    

    MongoDB Shell是一种JS,所以可以通过var来定义变量,可以通过find()方法来查找集合中的所有数据,相当于select * from users
    插入数据时,如果没有指定_id这个字段,系统会自动生成一个值,从该值中能够解析出插入文档的日期或者获取日期中的字符串值

    方式二:save()
    db.集合名字.save(Bson) : 如果要插入的文档没有指定_id,则插入文档,如果指定_id,如果集合中不包含_id,则插入文档,如果集合中已经存在相同的id值,则更会整体替换

    > db.users.find()
    { "_id" : 1, "username" : "mengday8" }
    { "_id" : 2, "username" : "mengday8" }
    > db.users.save({ "_id" : 3, "mengday9" : 20})
    WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 3 })
    > db.users.save({ "_id" : 2, "age" : 20, "gender": 1 })
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday8" }
    { "_id" : 2, "age" : 20, "gender" : 1 }
    { "_id" : 3, "mengday9" : 20 }
    >
    > db.users.save([{ "_id" : 4, "username": "mengday9"}, { "_id" : 5, "username":"mengday10"}])
    

    方式三: update()
    update({查询条件}, {更新的文档}, 是否开启addOrUpdate) : addOrUpdate为true,当集合中不存在的时候就插入,存在就更新

    > db.users.find()
    { "_id" : 5, "username" : "mengday10" }
    > db.users.update({"username" : "mengday11"}, { "_id" : 6, "age" : 20, "gender" : 1 }, true)
    WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 6 })
    > db.users.find()
    { "_id" : 5, "username" : "mengday10" }
    { "_id" : 6, "age" : 20, "gender" : 1 }
    >
    

    删除 remove

    remove({删除条件}): 删除满足条件的所有数据
    remove({删除条件}, true): 删除满足条件的第一条数据
    remove({}): 清空集合中的所有文档

    // 删除bson变量中的某个字段
    > var user = {"username": "mengday", "age": 26}
    > delete user.age
    > user
    { "username" : "mengday" }
    
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "password" : "123456" }
    { "_id" : 2, "username" : "mengday2", "password" : "123456" }
    { "_id" : 3, "username" : "mengday3", "password" : "123456", "age" : 18 }
    { "_id" : 4, "username" : "mengday4", "password" : "123456", "age" : 28 }
    { "_id" : 5, "username" : "mengday5", "password" : "123456", "age" : 38 }
    > db.users.remove({age: {$lt: 38}})
    WriteResult({ "nRemoved" : 2 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "password" : "123456" }
    { "_id" : 2, "username" : "mengday2", "password" : "123456" }
    { "_id" : 5, "username" : "mengday5", "password" : "123456", "age" : 38 }
    > db.users.remove({"password": "123456"}, true)
    WriteResult({ "nRemoved" : 1 })
    > db.users.find()
    { "_id" : 2, "username" : "mengday2", "password" : "123456" }
    { "_id" : 5, "username" : "mengday5", "password" : "123456", "age" : 38 }
    > db.users.remove({})
    WriteResult({ "nRemoved" : 2 })
    
    // findAndModify可以用来插入或更新upsert、也可以用来删除
    > db.users.findAndModify({
       "query": {"username": "mengday"},
       "remove": true
    })
    {
            "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
            "username" : "mengday",
            "addresses" : [
                    {
                            "city" : "shanghai",
                            "area" : "zhangjiang"
                    },
                    {
                            "city" : "beijing",
                            "area" : "CHAOYANG"
                    }
            ],
            "create_time" : ISODate("2017-07-29T09:09:14.031Z")
    }
    

    更新 update,findAndModify

    更新指定字段的值
    替换整个文档
    更新满足条件的第一条文档
    更新满足条件的所有文档

    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "age" : 38 }
    // 使用$set修改器修改指定字段, 当字段不存在时会创建并赋值
    > db.users.update({"username": "mengday5"}, {$set: {"age": 18}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "age" : 18 }
    
    // $unset 用于删除字段
    > db.users.update({"username": "mengday5"}, {"$unset": {"age": 1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456" }
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456" }
    
    // $push: 向数组的尾部添加一个元素,如果字段不存在则创建
    > db.users.update({"username": "mengday5"}, {"$push": {"hobby": "mm"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm" ] }
    > db.users.update({"username": "mengday5"}, {"$push": {"hobby": "money"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money" ] }
    >
    
    // $push + $each : 批量push
    > db.users.update({"username": "mengday5"}, {"$push": {"hobby": {"$each": ["play", "eat"]}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat" ] }
    >
    
    // $pushAll = $push + $each 批量push
    > db.users.update({"username": "mengday5"}, {"$pushAll": {"hobby": ["drink", "happy"]}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "mm", "money", "play", "eat", "drink", "happy" ] }
    
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456" }
    
    // $addToSet:不重复的set集合
    > db.users.update({}, {"$addToSet": {"hobby": "eat"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
    >
    > db.users.update({}, {"$addToSet": {"hobby": {"$each": ["eat", "drink"]}}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat", "drink" ] }
    >
    
    // $pop: 弹出数组的头部元素或尾部元素: -1:头部,1:尾部
    > db.users.update({}, {"$pop": {"hobby": 1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday5", "password" : "123456", "hobby" : [ "eat" ] }
    
    // $pull: 删除数组中的值
    > db.lists.insert({"no": [1, 1, 1, 3]})
    WriteResult({ "nInserted" : 1 })
    > db.lists.update({}, {"$pull": {"no": 1}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.lists.find()
    { "_id" : ObjectId("597c0a3087d089dfa7ce1be2"), "no" : [ 3 ] }
    >
    
    // 使用小标或者定位操作符$来操作数组
    > db.users.find()
    { "_id" : ObjectId("597c3c1587d089dfa7ce1be3"), "username" : "mengday", "addresses" : [ { "city" : "shanghai", "area" : "zhangjiang" }, { "city" : "be
    ijing", "area" : "chaoyang" } ] }
    >
    // 修改内嵌文档数组中第二个元素的值
    > db.users.update({"username": "mengday"}, {"$set": {"addresses.1.area": "chaoyangqu"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
            "username" : "mengday",
            "addresses" : [
                    {
                            "city" : "shanghai",
                            "area" : "zhangjiang"
                    },
                    {
                            "city" : "beijing",
                            "area" : "chaoyangqu"
                    }
            ]
    }
    
    // 定位操作符$: 查询条件一般是以数组中的元素为条件,使用$符号作为满足查询条件的第一条文档对应的下标值
    > db.users.update({"addresses.city": "beijing"}, {"$set": {"addresses.$.area": "CHAOYANG"}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.findOne()
    {
            "_id" : ObjectId("597c3c1587d089dfa7ce1be3"),
            "username" : "mengday",
            "addresses" : [
                    {
                            "city" : "shanghai",
                            "area" : "zhangjiang"
                    },
                    {
                            "city" : "beijing",
                            "area" : "CHAOYANG"
                    }
            ]
    }
    
    
    // 文档整体替换
    > db.users.update({"username": "mengday5"}, {"age": 17})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "age" : 17 }
    
    // 第三个参数: 插入或者更新,当_id不存在的时候插入,当_id值存在的时候更新
    > db.users.update({"_id": 2}, {"username": "mengday", "age": 16}, true)
    WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 2 })
    > db.users.find()
    { "_id" : 1, "age" : 17 }
    { "_id" : 2, "username" : "mengday", "age" : 16 }
    
    // 更新
    > db.users.update({"_id": 2}, {"username": "mengday2", "birthday": new Date()}, true)
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "age" : 17 }
    { "_id" : 2, "username" : "mengday2", "birthday" : ISODate("2017-07-25T06:33:10.579Z") }
    
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 16 }
    { "_id" : 2, "username" : "mengday2", "age" : 16 }
    
    // 更新满足条件的第一条文档
    > db.users.update({"age": 16}, {$set: {"age": 18}})
    WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 18 }
    { "_id" : 2, "username" : "mengday2", "age" : 16 }
    
    // 第三个参数:insertOrUpdate, 第四个参数:是否批量更新,true就是更新所有满足条件的文档
    > db.users.update({"age": {$gte: 16}}, {$set: {"age": 25}}, false, true)
    WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 })
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 25 }
    { "_id" : 2, "username" : "mengday2", "age" : 25 }
    >
    
    // 查询然后更新,更新是整体替换, 如果想更新指定的字段使用$set修改器即可
    > db.users.findAndModify({
        query: { "username": "mengday"},
        update:{
               "age": 20,
                "username": "mengday20"
        }
    })
    {
            "_id" : 1,
            "username" : "mengday",
            "age" : 20,
            "birthday" : ISODate("2017-07-25T07:05:28.286Z")
    }
    > db.users.find()
    { "_id" : 1, "age" : 20, "username" : "mengday20" }
    

    查询

    // 查询所有, 相当于 select * from users
    > db.users.find()
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    >
    
    // pretty() 用于格式化查询的结果
    > db.users.find().pretty()
    {
            "_id" : 1,
            "username" : "mengday",
            "age" : 20,
            "birthday" : ISODate("2017-07-25T07:05:28.286Z")
    }
    ...
    {
            "_id" : 5,
            "username" : "sunday",
            "age" : 37,
            "birthday" : ISODate("2017-07-25T07:07:45.420Z")
    }
    >
    
    // 查询一条, 相当于select * from users limit 1
    > db.users.findOne()
    {
            "_id" : 1,
            "username" : "mengday",
            "age" : 20,
            "birthday" : ISODate("2017-07-25T07:05:28.286Z")
    }
    
    // 查询条件, 相当于 select * from users where age < 20
    > db.users.find({"age": {$lt: 20}})
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    
    // 查询指定的字段,1:代表要查询的字段,0:代表不要查询的字段 ,相当于 select username, age from users where age < 20
    > db.users.find({"age": {$lt: 20}}, {"_id":0, "username": 1, "age": 1})
    { "username" : "tom", "age" : 18 }
    
    // and 条件,多个调剂直接用逗号分开,不需要什么操作符: 相当于 select * from users where age < 20 and id < 3
    > db.users.find({"age": {$lt: 30}, "_id": {$lt: 3 }})
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    
    // 同一个字段多个条件: 相当于 select * from users where age > 25 and age < 30
    > db.users.find({"age": {$gt: 25, $lt:30 }})
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    
    // or: 相当于 select * from users where age > 30 or username = 'tom'
    > db.users.find({$or: [{"age": {$gt: 30}}, {"username": "tom"}]})
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    
    // and or 混合使用,相当于 select * from users where id < 4 and (username = 'mengdat' or age < 20)
    > db.users.find({ $or: [{"username": "mengday"}, {"age": {$lt: 20}}], "_id": {$lt: 4} })
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    >
    
    // in: 相当于 select * from users where age in (18, 28)
    
    > db.users.find({"age": {$in: [18, 28]}})
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    >
    
    // 正则表达式不但可以匹配字符串还可以匹配字段值是正则表达式类型的,此时是相等匹配
    // 模糊查询,正则表达式: 以xiao开头,以ng结尾
    // 相当于 select * from users where username like 'xiao%' and username like '%ng'
    > db.users.find({"username": /^xiao/, "username": /ng$/})
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    
    > db.users.insert({"_id": 6, "username": "sunday", "age": 39, "birthday": new Date(), "hobby": ["eat
    ", "drink", "play", "happy", "money", "mm"] })
    WriteResult({ "nInserted" : 1 })
    
    // 正则表达式忽略大小写
    > db.users.find({"username": {$regex:/sunday/, $options:"$i"}})
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 正则表达式用于数组
    > db.users.find({"hobby": {$regex: "mm"}})
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 正则表达式包含变量时需要使用eval()函数来计算
    > var username = "sunday"
    > db.users.find({"username": {$regex:eval("/" + username + "/i")}})
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 数组字段: 值,意思就是这个数组中是否包含该元素,如果包含就是满足条件的
    > db.food.insert({"fruit": ["apple", "banana", "cherry"]})
    WriteResult({ "nInserted" : 1 })
    > db.food.find({"fruit": "banana"})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    
    // 当值是一个值时是是否包含,当值是数组时就是精确匹配了,此时匹配不到结果
    > db.food.find({"fruit":  ["apple", "cherry"]})
    // $all: 数组中同时都包含多个元素
    > db.food.find({"fruit": {$all: ["apple", "cherry"]}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    
    // 查询数组中指定的下标对应的值是否和给的值一样
    // 查询文档中的fruit中第三个元素的值是cherry的文档
    > db.food.find({"fruit.2": "cherry"})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    >
    
    // $size: 根据数组的长度进行筛选
    > db.food.find({"fruit": {$size: 3}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "cherry" ] }
    
    
    > db.food.find()
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana", "orange", "cherry" ]
    >
    // 返回数组中前两个元素
    > db.food.find({}, {"fruit": {$slice: 2}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "apple", "banana" ] }
    // 返回数组中后两个元素
    > db.food.find({}, {"fruit": {$slice: -2}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "orange", "cherry" ] }
    // 偏移下标为1,取2个长度,相当于 limint 0, 2
    > db.food.find({}, {"fruit": {$slice: [1, 2]}})
    { "_id" : ObjectId("597d353be210addac88b2a36"), "fruit" : [ "banana", "orange" ] }
    >
    
    
    > db.test.find()
    { "_id" : ObjectId("597d4342e210addac88b2a37"), "x" : [ 2, 5 ] }
    { "_id" : ObjectId("597d4350e210addac88b2a38"), "x" : [ 4, 5 ] }
    { "_id" : ObjectId("597d4367e210addac88b2a39"), "x" : [ 4, 10 ] }
    // $elemMatch: 数组中是否有一个元素同时满足所有条件(只要有一个元素满足就能匹配上)
    > db.test.find({"x": {"$elemMatch": {$gt: 5, $lt: 20}}})
    { "_id" : ObjectId("597d4367e210addac88b2a39"), "x" : [ 4, 10 ] }
    
    // 根据字段的数据类型来查询,2代码String
    > db.users.find({"username": {$type: 2}})
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    { "_id" : 2, "username" : "tom", "age" : 18, "birthday" : ISODate("2017-07-25T07:05:52.166Z") }
    { "_id" : 3, "username" : "xiaohong", "age" : 28, "birthday" : ISODate("2017-07-25T07:06:13.741Z") }
    { "_id" : 4, "username" : "xiaoming", "age" : 27, "birthday" : ISODate("2017-07-25T07:06:44.812Z") }
    { "_id" : 5, "username" : "sunday", "age" : 37, "birthday" : ISODate("2017-07-25T07:07:45.420Z") }
    { "_id" : 6, "username" : "SunDay", "age" : 39, "birthday" : ISODate("2017-07-25T07:53:16.072Z"), "h
    obby" : [ "eat", "drink", "play", "happy", "money", "mm" ] }
    
    // 查询文档中没有username字段的或者username的值是null
    > db.users.find({"username": null})
    // 查询文档中存在username字段,并且值是null, $in:[null]和username:null 一样的效果
    > db.users.find({"username": {$in: [null], $exists: true}})
    { "_id" : ObjectId("597c58f848c373e228a925a6"), "username" : null, "age" : 25 }
    { "_id" : ObjectId("597c591e48c373e228a925ab"), "username" : null, "age" : 24 }
    
    // 自定义筛选条件,通过js函数返回的boolean值来筛选,可以实现复杂条件的筛选
    > db.users.find({$where: function(){ return this.username == 'mengday' }})
    { "_id" : 1, "username" : "mengday", "age" : 20, "birthday" : ISODate("2017-07-25T07:05:28.286Z") }
    
    // 运行命令: 平常使用的很多命令如db.test.drop()底层都是调用的db.runCommand({"函数名":参数值})来实现的
    > db.runCommand({"drop": "test"})
    { "ns" : "test.test", "nIndexesWas" : 1, "ok" : 1 }
    // db.getLastError 和 db.runCommand({getLastError: 1}) 是一样的
    > db.getLastError
    > db.runCommand({getLastError: 1})
    
    ### 游标
    
    游标: 将查询结果赋值给一个局部变量,这个局部变量就是游标, 使用游标时shell并不理解查询数据库,而是等待真正开始要求获取结果时(调用hasNext()或者next()方法)才发送查询,这样在执行之前可以给查询附加额外的选项,如skip、limit、sort等,游标是一次性的,即用过一次即销毁
    

    var cursor = db.users.find()
    while(cursor.hasNext()){
    user = cursor.next();
    print(user);
    }

    // 需要重新查新赋值一个游标,上一个游标已经销毁

    var cursor = db.users.find()
    cursor.forEach(function(x){
    print(x);
    });

    // 查询两条文档 , 相当于 select id, username from users limit 2

    db.users.find({}, {“username”: 1}).limit(2)
    { “_id” : 1, “username” : “mengday” }
    { “_id” : 2, “username” : “tom” }

    // 分页第一种方法使用skip和limit函数, skip(2) 是指的offset, 相当于 select id, username from users limit 2,2

    db.users.find({}, {“username”: 1}).skip(2).limit(2)
    { “_id” : 3, “username” : “xiaohong” }
    { “_id” : 4, “username” : “xiaoming” }

    // sort 排序, 1:升续, 2:降续

    db.users.find({}, {“username”: 1}).skip(2).limit(2).sort({“age”: 1})
    { “_id” : 4, “username” : “xiaoming” }
    { “_id” : 3, “username” : “xiaohong” }

    // 分页第二种方法:使用sort和limit函数

    db.users.find()
    { “_id” : 1, “username” : “mengday1”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:52:33.837Z”) }
    { “_id” : 2, “username” : “mengday2”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:52:43.021Z”) }
    { “_id” : 3, “username” : “mengday3”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:52:53.420Z”) }
    { “_id” : 4, “username” : “mengday4”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:53:00.299Z”) }
    { “_id” : 5, “username” : “mengday5”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:53:07.826Z”) }
    { “_id” : 6, “username” : “mengday6”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:53:13.290Z”) }
    { “_id” : 7, “username” : “mengday7”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:54:36.710Z”) }
    { “_id” : 8, “username” : “mengday8”, “age” : 26, “create_date” : ISODate(“2017-07-30T07:54:40.262Z”) }

    // 先根据日期进行排序,获取第一页数据时直接使用limit指定获取的条数,将结果赋值给局部变量,然后循环该游标,记录下最后一条文档对应的日期值

    var page1 = db.users.find().sort({“create_date”: 1}).limit(5);
    var latest = null;
    while(page1.hasNext()){
    … latest = page1.next();
    … print(“page1:” + latest.username);
    … }
    page1:mengday1
    page1:mengday2
    page1:mengday3
    page1:mengday4
    page1:mengday5

    // 获取后面的页:将上一页保存的文档对应的时间作为下一页查询的条件,因为还好对时间进行排序,又过滤掉之前的数据,相当于skip的效果,然后再获取指定的条数

    var page2 = db.users.find({“create_date”: {$gt: latest.create_date}}).sort({“create_date”: 1}).limit(5);
    while(page2.hasNext()){
    … latest = page2.next();
    … print(“page2:” + latest.username);
    … }
    page2:mengday6
    page2:mengday7
    page2:mengday8

    
    ### 聚合操作
    
    

    // distinct: 查询某个字段的所有不重复的值, 相当于 select distinct age from users

    db.users.distinct(“age”)
    [ 20, 18, 28, 27, 37, 39 ]

    
    // 分组: key: 要分组的字段, initial:值的初始化, condition:是筛选条件,$reduce:将满足的条件的所有文档都会执行该函数,finalize:每组函数执行完之后的操作,可以做一些统计什么的
    db.users.group({ 
    	"key": {"age": true}, 
    	"initial": {"user": []}, 
    	"$reduce": function(cur, prev){
    						prev.user.push(cur) ;
    			   },
    	"condition": {"age": {$lt:25}},
    	"finalize": function(out) {
    		out.count = out.user.length;
    	}
    })
    
    [
            {
                    "age" : 20,
                    "user" : [
                            {
                                    "_id" : 1,
                                    "age" : 20,
                                    "username" : "mengday20"
                            }
                    ],
                    "count" : 1
            },
            {
                    "age" : 18,
                    "user" : [
                            {
                                    "_id" : 2,
                                    "username" : "tom",
                                    "age" : 18,
                                    "birthday" : ISODate("2017-07-25T07:05:52.166Z")
                            }
                    ],
                    "count" : 1
            }
    ]
    >
    
    
    
    分享一个朋友的人工智能教程。比较通俗易懂,风趣幽默,感兴趣的朋友可以去看看。

    官方文档: https://docs.mongodb.com/manual/reference/method/

    展开全文
  • 2. mongocxx 续上一篇,接着看一下mongocxx中的文件有些什么。 先看一下基本的增删改查操作: 2.1 connect.cpp 数据库的链接 参见之前的博客。...构造一个文档,插入数据库中的一个collection。...#include

    2. mongocxx

    续上一篇,接着看一下mongocxx中的文件有些什么。
    这里写图片描述
    先看一下基本的增删改查操作:

    2.1 connect.cpp 数据库的链接

    参见之前的博客。

    2.2 create.cpp 构造文档并插入

    构造一个文档,插入数据库中的一个collection。关于builder::stream::document的使用见同系列博客之(三)。

    #include <bsoncxx/builder/stream/document.hpp>
    #include <bsoncxx/types.hpp>
    
    #include <mongocxx/client.hpp>
    #include <mongocxx/instance.hpp>
    #include <mongocxx/uri.hpp>
    
    using bsoncxx::builder::stream::document;
    using bsoncxx::builder::stream::open_document;
    using bsoncxx::builder::stream::close_document;
    using bsoncxx::builder::stream::open_array;
    using bsoncxx::builder::stream::close_array;
    using bsoncxx::builder::stream::finalize;
    
    int main(int, char**) {
        mongocxx::instance inst{};
        mongocxx::client conn{mongocxx::uri{}};
    
        auto db = conn["test"];
    
        // TODO: fix dates
    
        // @begin: cpp-insert-a-document
        bsoncxx::document::value restaurant_doc =
            document{} << "address" << open_document << "street"
                       << "2 Avenue"
                       << "zipcode"
                       << "10075"
                       << "building"
                       << "1480"
                       << "coord" << open_array << -73.9557413 << 40.7720266 << close_array
                       << close_document << "borough"
                       << "Manhattan"
                       << "cuisine"
                       << "Italian"
                       << "grades" << open_array << open_document << "date"
                       << bsoncxx::types::b_date{std::chrono::milliseconds{12323}} << "grade"
                       << "A"
                       << "score" << 11 << close_document << open_document << "date"
                       << bsoncxx::types::b_date{std::chrono::milliseconds{121212}} << "grade"
                       << "B"
                       << "score" << 17 << close_document << close_array << "name"
                       << "Vella"
                       << "restaurant_id"
                       << "41704620" << finalize;
    
        // We choose to move in our document here, which transfers ownership to insert_one()
        auto res = db["restaurants"].insert_one(std::move(restaurant_doc));
        // @end: cpp-insert-a-document
    }
    

    在数据库test中的restaurant”表”(collection)中插入一个文件restaurant_doc:

     {
         "address" : {
                         "street"   :"2 Avenue",
                         "zipcode"  :"10075",
                         "building" :"1480", 
                         "coord"    :[-73.9557413,40.7720266],
                     },
        "borough" : "Manhattan",
        "cuisine" : "Italian",
        "grades"  : [ 
                       {
                           "date"  : ***时间,
                           “grade" : "A",
                           "score" : 11
                       }
                       {
                           "date"  : ***时间,
                           ”grade" : "B",
                           "score" : 17
                       }
                   ]
        "name"          : "Vella",
        "restaruant_id" : "41706420"
    }

    2.3 update.cpp

    • 找到一个符合条件的文档,修改/新建一个键值对
    • 嵌套修改/新建一个键值对
    • 修改多个文件中的键值对
    • 找到一个符合条件的文档,替换文档中的一部分内容
    int main(int, char**) {
        mongocxx::instance inst{};
        mongocxx::client conn{mongocxx::uri{}};
    
        auto db = conn["test"];
    
        // Update top-level fields in a single document.
        {
            // @begin: cpp-update-top-level-fields
            //找到有"name":"Juni"键值对的文档,使用\$set指定一个  
            //"cuisine"(如果文档中没有将新建),将这个键值对改
            //"cuisine":"American(New)",然后使用\$currentDate指定
            //叫做"lastModified"的键,bool值true表示这个键对应的值使用
            //Date的形式(见此系列(2)中的常用数据类型
            //使用Unix的时间格式记录下当前的时间。
            bsoncxx::builder::stream::document filter_builder, update_builder;
            filter_builder << "name"
                           << "Juni";
            update_builder << "$set" << open_document << "cuisine"
                           << "American (New)" << close_document << "$currentDate" << open_document
                           << "lastModified" << true << close_document;
    
            db["restaurants"].update_one(filter_builder.view(), update_builder.view());
            // @end: cpp-update-top-level-fields
        }
    
        // Update an embedded document in a single document.
        //找到restaurant_id是41156888的这家餐馆的信息,把地址信息(文档)里面的street改成East 31st Street
        {
            // @begin: cpp-update-embedded-field
            bsoncxx::builder::stream::document filter_builder, update_builder;
            filter_builder << "restaurant_id"
                           << "41156888";
            update_builder << "$set" << open_document << "address.street"
                           << "East 31st Street" << close_document;
    
            db["restaurants"].update_one(filter_builder.view(), update_builder.view());
            // @end: cpp-update-embedded-field
        }
    
        // Update multiple documents.
        {
            // @begin: cpp-update-multiple-documents
            bsoncxx::builder::stream::document filter_builder, update_builder;
            filter_builder << "address.zipcode"
                           << "10016"
                           << "cuisine"
                           << "Other";
            update_builder << "$set" << open_document << "cuisine"
                           << "Category To Be Determined" << close_document << "$currentDate"
                           << open_document << "lastModified" << true << close_document;
    
            db["restaurants"].update_many(filter_builder.view(), update_builder.view());
            // @end: cpp-update-multiple-documents
        }
    
        // Replace the contents of a single document.
        {
            // @begin: cpp-replace-document
            //找到含有filter_builder信息的文档,将其中的对应信息替换成
            //replace_builder的信息
            bsoncxx::builder::stream::document filter_builder, replace_builder;
            filter_builder << "restaurant_id"
                           << "41704620";
            replace_builder << "name"
                            << "Vella 2"
                            << "address" << open_document << "coord" << open_array << -73.9557413
                            << 40.7720266 << close_array << "building"
                            << "1480"
                            << "street"
                            << "2 Avenue"
                            << "zipcode"
                            << "10075" << close_document;
    
            db["restaurants"].replace_one(filter_builder.view(), replace_builder.view());
            // @end: cpp-replace-document
        }
    }

    2.4 remove.cpp:

    • 删除一个或多个collection中符合条件的document
    • 删除collection中所有的document
    • 删除collection
    int main(int, char**) {
        mongocxx::instance inst{};
        mongocxx::client conn{mongocxx::uri{}};
    
        auto db = conn["test"];
    
        // Remove all documents that match a condition.
        {
            // @begin: cpp-remove-matching-documents
            //删除有"borough":"Manhattan"键值对的document
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "borough"
                           << "Manhattan";
    
            db["restaurants"].delete_many(filter_builder.view());
            // @end: cpp-remove-matching-documents
        }
    
        // Remove one document that matches a condition.
        {
            // @begin: cpp-remove-justone
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "borough"
                           << "Queens";
    
            db["restaurants"].delete_one(filter_builder.view());
            // @end: cpp-remove-justone
        }
    
        // Remove all documents in a collection.
        {
            // @begin: cpp-remove-all-documents
            db["restaurants"].delete_many({});
            // @end: cpp-remove-all-documents
        }
    
        // Drop a collection.
        {
            // @begin: cpp-drop-collection
            db["restaurants"].drop();
            // @end: cpp-drop-collection
        }
    }

    2.5 query.cpp:

    • 查询一个collection中所有的文件
    • 条件查询含有某个键值对的document
    • 条件查询含有某个键值对(值为document,在document中继续嵌套查询)
    • 条件查询含有某个键值对(值为array,在array中继续嵌套查询)
    • 使用$gt(greater than),$lt(less than)进行条件查询
    • 多个条件查询 相当于sql里的and
    • 满足多个条件中至少一个条件查询,相当于sql中的or]
    • 对查询结果进行排序
    int main(int, char**) {
        mongocxx::instance inst{};
        mongocxx::client conn{mongocxx::uri{}};
    
        auto db = conn["test"];
    
        // Query for all the documents in a collection.
        //查询test数据库的restaurants集合中的所有文档
        {
            // @begin: cpp-query-all
            auto cursor = db["restaurants"].find({});
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-all
        }
    
        // Query for equality on a top level field.
        //查询restaurants集合中所有含"borough":"Manhattan"键值对的文档
        {
            // @begin: cpp-query-top-level-field
            auto cursor = db["restaurants"].find(document{} << "borough"
                                                            << "Manhattan" << finalize);
    
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-top-level-field
        }
    
        // Query by a field in an embedded document.
        //嵌套查询,查询邮编为10075的餐馆的文档,address是文档中嵌套的一个文档,zipcode是address中的一个key,10075是zipcode对应的value.
        {
            // @begin: cpp-query-embedded-document
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "address.zipcode"
                           << "10075";
    
            auto cursor = db["restaurants"].find(filter_builder.view());
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-embedded-document
        }
    
        // Query by a field in an array.
        //grades键对应的值是一个array,里面有两个文档,在这个数组中查找grade键的值是B的文档
        {
            // @begin: cpp-query-field-in-array
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "grades.grade"
                           << "B";
    
            auto cursor = db["restaurants"].find(filter_builder.view());
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-field-in-array
        }
    
        // Query with the greater-than operator ($gt).
        //在grades对应的array中寻找score大于30的文档
        {
            // @begin: cpp-query-greater-than
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "grades.score" << open_document << "$gt" << 30 << close_document;
    
            auto cursor = db["restaurants"].find(filter_builder.view());
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-greater-than
        }
    
        // Query with the less-than operator ($lt).
        //$gt和$lt,分别是大于和小于
        {
            // @begin: cpp-query-less-than
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "grades.score" << open_document << "$lt" << 10 << close_document;
    
            auto cursor = db["restaurants"].find(filter_builder.view());
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-less-than
        }
    
        // Query with a logical conjunction (AND) of query conditions.
        //filter_builder中有多个键值对,默认是and的关系,相当于SQL语句中的and,表示查询cuisine是Italian并且zipcode是10075的餐馆的文档
        {
            // @begin: cpp-query-logical-and
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "cuisine"
                           << "Italian"
                           << "address.zipcode"
                           << "10075";
    
            auto cursor = db["restaurants"].find(filter_builder.view());
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-logical-and
        }
    
        // Query with a logical disjunction (OR) of query conditions.
        //$or表示或的关系注意这个地方open_array/close_array和open_document/close_document的使用
        {
            // @begin: cpp-query-logical-or
            bsoncxx::builder::stream::document filter_builder;
            filter_builder << "$or" << open_array << open_document << "cuisine"
                           << "Italian" << close_document << open_document << "address.zipcode"
                           << "10075" << close_document << close_array;
    
            auto cursor = db["restaurants"].find(filter_builder.view());
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-logical-or
        }
    
        // Sort query results.
        //1和-1表示升序和降序(应该是)
        {
            // @begin: cpp-query-sort
            mongocxx::options::find opts;
            bsoncxx::builder::stream::document order_builder;
            order_builder << "borough" << 1 << "address.zipcode" << -1;
            opts.sort(order_builder.view());
    
            auto cursor = db["restaurants"].find({}, opts);
            for (auto&& doc : cursor) {
                std::cout << bsoncxx::to_json(doc) << std::endl;
            }
            // @end: cpp-query-sort
        }
    }

    2.6 get_values_from_documents.cpp

    从数据库的文档中取数据,输出到cout

    using bsoncxx::builder::stream::document;
    using bsoncxx::builder::stream::close_array;
    using bsoncxx::builder::stream::finalize;
    using bsoncxx::builder::stream::open_array;
    using bsoncxx::type;
    
    // Document model, showing array with nested documents:
    //
    // {
    //     "_id" : ObjectId(...),
    //     "messagelist" : [
    //       {
    //         "uid" : 413098706,
    //         "status" : 2,
    //         "msg": "..."
    //       },
    //       ...
    //     ]
    // }
    
    // Construct a document in the format of 'messagelist'.
    bsoncxx::document::value new_message(int64_t uid, int32_t status, std::string msg) {
        document doc;
        return doc << "uid" << uid << "status" << status << "msg" << msg << finalize;
    }
    
    // Insert a document into the database.
    void insert_test_data(mongocxx::collection& coll) {
        document builder{};
        //这种赋值方法注意一下
        builder << "messagelist" << open_array << new_message(413098706, 3, "Lorem ipsum...")
                << new_message(413098707, 2, "Lorem ipsum...")
                << new_message(413098708, 1, "Lorem ipsum...") << close_array;
    
        bsoncxx::document::value doc = builder << finalize;
    
        // Normally, one should check the return value for success.
        coll.insert_one(doc.view());
    }
    
    // Iterate over contents of messagelist.遍历messagelist数组中的所有内容
    void iterate_messagelist(const bsoncxx::document::element& ele) {
        // Check validity and type before trying to iterate.
        if (ele.type() == type::k_array) {
            bsoncxx::array::view subarray{ele.get_array().value};
            for (const bsoncxx::array::element& msg : subarray) {
                // Check correct type before trying to access elements.
                // Only print out fields if they exist; don't report missing fields.
                if (msg.type() == type::k_document) {
                    bsoncxx::document::view subdoc = msg.get_document().value;
                    bsoncxx::document::element uid = subdoc["uid"];//使用[]访问键
                    bsoncxx::document::element status = subdoc["status"];
                    bsoncxx::document::element msg = subdoc["msg"];
                    if (uid && uid.type() == type::k_int64) {
                        std::cout << "uid: " << uid.get_int64().value << std::endl;
                    }
                    if (status && status.type() == type::k_int32) {
                        std::cout << "status: " << status.get_int32().value << std::endl;
                    }
                    if (msg && msg.type() == type::k_utf8) {
                        std::cout << "msg: " << msg.get_utf8().value << std::endl;
                    }
                } else {
                    std::cout << "Message is not a document" << std::endl;
                }
            }
        } else {
            std::cout << "messagelist is not an array" << std::endl;
        }
    }
    
    // Print document parts to standard output.
    void print_document(const bsoncxx::document::view& doc) {
        // Extract _id element as a string.
        bsoncxx::document::element id_ele = doc["_id"];
        if (id_ele.type() == type::k_oid) {
            std::string oid = id_ele.get_oid().value.to_string();//注意 _id可以通过to_string()转为std::string
            std::cout << "OID: " << oid << std::endl;
        } else {
            std::cout << "Error: _id was not an object ID." << std::endl;
        }
    
        // Extract "messagelist" element, which could be the 'invalid' (false)
        // element if it doesn't exist.
        bsoncxx::document::element msgs_ele = doc["messagelist"];
        if (msgs_ele) {
            iterate_messagelist(msgs_ele);
        } else {
            std::cout << "Error: messagelist field missing." << std::endl;
        }
    }
    
    void iterate_documents(mongocxx::collection& coll) {
        // Execute a query with an empty filter (i.e. get all documents).
        mongocxx::cursor cursor = coll.find({});
    
        // Iterate the cursor into bsoncxx::document::view objects.
        for (const bsoncxx::document::view& doc : cursor) {
            print_document(doc);
        }
    }
    
    int main() {
        mongocxx::instance inst{};
        mongocxx::client client{mongocxx::uri{}};
        mongocxx::collection coll = client["test"]["events"];
    
        coll.drop();
        insert_test_data(coll);
        iterate_documents(coll);
    }
    

    简单分析了增删改查的基本用法,之后再通过看API了解更详细的使用方法。下一篇博客把常用的类和成员函数,相关参数梳理一下。
    还有几个感觉比较有用的例子:
    aggregate.cpp :用来统计

    index.cpp:建索引
    bulk_write.cpp:批量操作
    instance_management.cpp:对instance进行管理,项目大的时候会需要,保持分配给mongocxx::instance和mongocxx::pool对象的堆用一种允许动态配置的方式连接起来。

    展开全文
  • 一、什么是MongoDB ? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能数据...
  • MongoDB一步一步学开发》(Windows10) 六、插入第一个文档 插入文档语法格式 MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下: db.COLLECTION_NAME.insert(document) db.COLLECTION...
  • 不过重点在于如何让这个程序真正可以跑起来显示出来结果,着实费了一番功夫。 1 #include 2 #include "client/dbclient.h" 3 4 using namespace mongo; 5 using namespace std;... 8 c.conne
  • 部分内容摘自runoob.comMongoDB简介MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。 在高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 旨在为WEB应用提供可扩展的高性能...
  • MongoDB是什么?看完你就知道了

    万次阅读 多人点赞 2019-09-03 14:18:19
    最近在回顾mongodb的相关知识,输出一篇文章做为MongoDB知识点的总结。 总结的目的在于回顾MongoDB的相关知识点,明确MongoDB在企业级应用中充当的角色,为之后的技术选型提供一个可查阅的信息简报 一、...
  • 什么是MongoDB ? MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。 MongoDB 可在高负载的情况下,添加更多的节点,可以保证服务器性能。 MongoDB 可为Web应用提供可扩展的高性能数据存储...
  • MongoDB 优缺点

    万次阅读 2018-03-22 15:13:24
    mongodb与关系型数据库相比的优缺点与关系型数据库相比,MongoDB的优点:①弱一致性(最终一致),更能保证用户的访问速度:举例来说,在传统的关系型数据库中,一个COUNT类型的操作会锁定数据集,这样可以保证得到...
  • MongoDB中文手册(4.2版本)

    千次阅读 2020-06-01 18:44:25
    MongoDB简介  1 基础入门  2 数据库和集合   2.1 视图    2.2 按需实例化视图   2.3 固定集合  3 文档  4 BSON类型   4.1 比较和排序   4.2 扩展JSON(V2)   4.3 扩展JSON(V1) ...
  • MongoDB是什么?看完你就知道了!

    千次阅读 2019-08-22 13:52:23
    点击上方"Java学习之道",选择"关注"公众号每天10:24,干货准时送达!来源:http://suo.im/5e8a94一、概述1.MongoDB是什么?用一句话总结...
  • Windows系统 MongoDB 各个64位版本下载地址

    万次阅读 多人点赞 2016-11-22 14:20:30
    MongoDB Windows系统各个64位版本下载地址: http://dl.mongodb.org/dl/win32/x86_64 MongoDB Windows系统各个64位版本下载地址: http://dl.mongodb.org/dl/win32/x86_64
  • linux mongodb安装和配置启动图文详解

    万次阅读 2017-04-25 09:01:23
    一.前期准备 1.Win7环境下 官网下载Mongodb包 本文使用mongodb-linux-...1.解压和复制mongodb至目录 /usr/local/mongodb cd /opt/software tar -zxvf mongodb-linux-x86_64-3.2.12.tgz cp -r mongodb-linux-x86_64-3
  • Linux以tar包方式安装MongoDB-4.2.8

    万次阅读 2020-06-28 13:15:03
    tar -zxvf mongodb-linux-x86_64-4.2.8.tgz 创建目录,设置权限 在根目录 / 下创建data/db目录,用于放置mongodb数据,并且给该目录设置权限 sudo mkdir -p /data/db sudo chown -R 自己电脑的用户名 /data ...
  • MongoDB】学习MongoDB推荐三本书

    万次阅读 2014-11-18 23:19:01
    最近学习mongodb,感觉这三本书写得不错,很大家分享一下:
  • 1.新建数据库 2.新建集合(表) 3.删除集合,删除数据库 4.新增数据 5.删除数据 6.修改数据 7.查询数据
1 2 3 4 5 ... 20
收藏数 212,769
精华内容 85,107
关键字:

mongodb