M001: MongoDB Basics 笔记

Posted by Waynerv on

category: 数据库

Tags: MongoDB

Chapter1: Introduction

使用Compass连接MongoDB

compass是MongoDB官方出品的数据库Client,可通过可视化页面进行简单的数据筛选和查询,以及直接访问修改文件对象(比MySQL Workbench好多了)。

数据库,集合,文档

数据库相当于MySQL中的database(使用数据库前也要先use),集合类似于MySQL中的表(table),文档相当于MySQL中的一条记录(row)。

区别:MongoDB不要求同一集合中的文档具备相同的schema,即不同的文档可以拥有不同的字段,不像MySQL使用统一的列,因此MongoDB具备更高的可扩展性。

标量值类型

MongoDB中的value标量类型有常见的String, Int32, Int64, Double, Array, Object, Date的等。注意所有的key都为字符串类型。

字段可以自由的多层嵌套文档(object)、数组等类型

地理数据

MongoDB中可以存储地理位置数据(如坐标数组),在Compass中还可以使用第三方服务将地理位置信息可视化,并进行方便的区域查询。

通过查询筛选集合

在Compass客户端中,可以方便的通过可视化操作对文档进行筛选,并通过拖拽选择筛选区间。

mongo Shell对应的查询语句为db.collection.find({'key': 'value'})

在任何场景下都在key的首尾使用引号是一种良好实践。

理解JSON

参考资料

JSON建构于两种结构:键值对的(无序)集合,以及值的有序列表。

JSON的键均为字符串(string)。

JSON的值(value)可以是双引号括起来的字符串(string)、数值(number)、truefalsenull、对象(object)或者数组(array)。这些结构可以嵌套。

Chapter2: The MongoDb Query Language

安装MongoDB和mongo Shell

官方tutorialInstall MongoDB Community Edition on Ubuntu

  1. 导入MongoDB public GPG Key.

    sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
    
  2. 在指定位置为MongoDB创建list文件

    echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
    
  3. 更新包列表

    sudo apt-get update
    
  4. 安装最新版本的MongoDB包

    sudo apt-get install -y mongodb-org
    
  5. 运行MongoDB

    启动Mongod服务:

    sudo service mongod start
    

    启动mongo Shell

    mongo
    

创建沙盒集群并加载数据

在Atlas网站根据引导创建账户,建立沙盒集群,在Security页面中设置User及IP Whitelist,并通过mongo Shell与Compass进行连接。

建立连接后在mongo shell内使用load('文件名')加载指定文件到沙盒集群。

Creating Documents创建文档

除了以下两个主要方法,update行为中的upsert也可以创建新的文档。

insertOne()

首先需要指定数据库,该指令是针对集合的操作。示例:

db.movies.insertOne({"title": "Star Trek 2", "year": 1982, "imdb": "tt0084726"})

insertMany()

多个文档组成数组作为insertMany()的参数,示例:

db.inventory.insertMany([
   { item: "journal", qty: 25, tags: ["blank", "red"], size: { h: 14, w: 21, uom: "cm" } },
   { item: "mat", qty: 85, tags: ["gray"], size: { h: 27.9, w: 35.5, uom: "cm" } },
   { item: "mousepad", qty: 25, tags: ["gel", "blue"], size: { h: 19, w: 22.85, uom: "cm" } }
])

ordered inserts

ordered inserts (默认):insertMany过程中遭遇错误(如_id重合)将停止后续文档的插入

unordered inserts:为insertMany()方法增加第二个参数{"ordered": false}。遭遇错误时不会停止后续文档的插入。

Insert Behavior

MongoDB中所有文档都需要一个作为主键的值唯一的_id字段,如果新增一个文档忽略了该字段,MongoDB驱动将自动生成一个ObjectId作为_id字段的值,也可在创建时自行指定_id字段。

若集合不存在,将同时创建集合。

Reading Documents查询文档

查询所有集合中所有文档:

db.inventory.find( {} )

标量字段查询

等值查询:

db.inventory.find( { status: "D" } )

多重嵌套查询,使用圆点记法"field.nestedField":

db.inventory.find( { "size.uom": "in" } )

数组字段查询

匹配整个数组:

db.inventory.find( { tags: ["red", "blank"] } )

匹配数组中的单个元素:

db.inventory.find( { tags: "red" } )

匹配数组中的多个元素(使用$all操作符),不考虑顺序及其他元素:

db.inventory.find( { tags: { $all: ["red", "blank"] } } )

匹配数组中特定位置的元素(使用圆点标记法表示索引位置):

db.inventory.find( { "dim_cm.1": { $gt: 25 } } )

Cursors游标

<code>db.collection.find()</code> 方法返回一个指向匹配文档的 cursor (游标)。默认情况下一次最多返回20个结果,在Mongo Shell中可输入it进行迭代。

Projections映射

默认情况查询返回的文档会显示所有字段,在find()方法中设置projection参数(第二个参数)可设置返回结果中显示的字段,以减少网络损耗。设置方式:

{ field1: <value>, field2: <value> ... }

<value> 的值如下:

  • 1 或者 true 在返回的文档中包括该字段。
  • 0 或者 false 排除字段。

Updating Documents更新文档

updateOne()

更新满足筛选条件的第一个文档(可进行嵌套):

db.inventory.updateOne(
   { item: "paper" }, // 筛选条件,除了等值筛选还可使用操作符进行范围筛选
   {
     $set: { 
        "size.uom": "cm", status: "P" 
     }, // 更新操作符:更新指定字段的值为value,如果没有该字段则新增
     $currentDate: { 
        lastModified: true 
     } // 更新`lastModified` 字段的值到当前日期,如果没有该字段则新增
   }
)

Update Operators更新操作符

常用更新操作符(参考文档):

  • $unset:删除指定字段

  • $inc:将指定字段值递增指定的数值

  • $push:增加一个元素到数组

    { $push: { <field1>: <value1>, ... } }
    
  • $pull:删除满足筛选条件的所有数组元素

  • $each:协助 <code>$push</code><code>$addToSet</code> 操作符分别新增多个元素到指定的数组(新增过程中报错不会阻塞)

updateMany()

更新满足筛选条件的所有文档,其他与updateOne()相同。

Upserts

如果<code>updateOne()</code>, <code>updateMany()</code>, 或者 <code>replaceOne()</code> 方法中包括了参数 upsert : true 而且 没有与筛选条件匹配的文档, 该操作将创建一个新文档并插入到集合。如果有匹配筛选条件的文档,该操作将更新或替换匹配的文档。

可以理解为:update or insert.

replaceOne()

使用作为第二个参数的新文档替换满足筛选条件的文档

Update Behavior

文档一旦创建,_id字段的值无法更新或替换。

Deleting Documents删除文档

删除集合中所有文档:

db.inventory.deleteMany({})

删除所有匹配条件的文档,向 <code>deleteMany()</code> 方法内传入筛选参数:

db.inventory.deleteMany({ status : "A" })

删除匹配条件的第一个文档:

db.inventory.deleteOne( { status: "D" } )

删除操作不会删除索引,即使删除集合中的所有文档也不会删除索引文件。

Atomicity原子性

MongoDB中所有的写操作在单个文档层面是原子性的(参考事务的提交与回滚,不会在单个文档的写过程中断)。

Chapter3:Deeper dive on the MongoDB Query Language

比较操作符

同类型BSON值的比较操作符如下:

Name Description
<code>$eq</code> equal 相等
<code>$gt</code> greater than 大于
<code>$gte</code> greater than or equal 大于或等于
<code>$in</code> in 在数组当中
<code>$lt</code> less than 小于
<code>$lte</code> less than or equal 小于或等于
<code>$ne</code> not equal 不等于
<code>$nin</code> none of the values specified in an array. 不在数组当中

示例:

cursor = db.inventory.find({"status": {"$in": ["A", "D"]}})
db.movieDetails.find({runtime:{$gt: 90, $lte:120}})

元素操作符

查询元素是否存在以及判断类型

Name Description
<code>$exists</code> 匹配存在特定字段的文档
<code>$type</code> 匹配特定字段特定类型的文档

示例,在trips集合中查找tripduration字段值为null且忽略不存在该字段的文档:

db.trips.find({tripduration: {$exists: true, $type: "null"}})

逻辑操作符

Name Description
<code>$and</code> Joins query clauses with a logical AND returns all documents that match the conditions of both clauses.
<code>$not</code> Inverts the effect of a query expression and returns documents that do not match the query expression.
<code>$nor</code> Joins query clauses with a logical NOR returns all documents that fail to match both clauses.
<code>$or</code> Joins query clauses with a logical OR returns all documents that match the conditions of either clause.

语法:

  • { $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN>} ] }
  • { field: { $not: { <operator-expression> } } }
  • { $nor: [ { <expression1> }, { <expression2> }, ... { <expressionN> } ] }
  • { $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }

示例:

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

数组操作符

Name Description
<code>$all</code> 匹配包含指定查询中所有指定元素的数组(不考虑顺序与是否存在其他元素)
<code>$elemMatch</code> 选择数组字段中有至少一个元素匹配所有指定<code>$elemMatch</code> 条件的文档。
<code>$size</code> x选择指定数组大小的文档

示例:

db.inventory.find( { tags: { $all: [ "appliance", "school", "book" ] } } )
{ _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 } } } }
)
db.collection.find( { field: { $size: 1 } } );

正则表达式操作符

在查询中使用通过正则操作符使用模式匹配字符串。MongoDB使用的正则表达式版本为 PCRE version 8.41 with UTF-8 support。

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

或:

{ <field>: /pattern/<options> }

示例:

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

注:转载本文,请与作者联系




如果觉得文章对您有价值,请作者喝杯咖啡吧

|
donate qrcode

欢迎通过微信与我联系

wechat qrcode

0 Comments latest

No comments.