欢迎光临散文网 会员登陆 & 注册

MongoDB基础

2022-11-16 16:14 作者:苦茶今天断更了吗  | 我要投稿

MongoDB是一个开源, 高性能, 无模式的文档型数据库, 用于简化开发和方便扩展, 属于NoSQL数据库,是最像关系型数据库(MySQL)的非关系型数据库。

MongoDB中的记录是一个文档, 它是一个由字段值对(field:value)组成的数据结构。

MongoDB文档类似于JSON对象, 即一个文档认为就是一个对象。

字段的数据类型是字符型, 它的值除了使用基本的一些类型外, 还可以包括其他文档, 普通数组和文档数组。

 

MongoDB 数据模型是面向文档的, 所谓文档就是一种类似于 JSON 的结构。

数据库 (database):一个仓库, 存储集合 (collection)

集合 (collection):类似于数组, 在集合中存放文档

文档 (document):文档型数据库的最小单位, 通常情况, 我们存储和操作的内容都是文档

 

在 MongoDB 中, 数据库和集合都不需要手动创建, 当创建文档时, 如果文档所在的集合或者数据库不存在, 则会自动创建数据库或者集合。

 

MongoDB 的特点:

高性能

提供高性能的数据持久化

嵌入式数据模型的支持减少了数据库系统上的 I/O 活动

索引支持更快的查询, 可包含来自嵌入式文档和数组的键

mmapv1, wiredtiger等多引擎支持满足各种场景需求

Gridfs 解决文件存储需求

高可用

MongoDB 的复制工具称作副本集 (replica set) 可以提供自动故障转移和数据冗余

高扩展

水平扩展

分片将数据分布在一组集群的机器上 (海量数据存储,服务能力水平扩展)

MongoDB 支持基于片键创建数据区域,在一个平衡的集群当中, MongoDB 将一个区域所覆盖的读写只定向到该区域的那些片

 

其他

MongoDB支持丰富的查询语言, 支持读和写操作(CRUD), 比如数据聚合, 文本搜索和地理空间查询等. 无模式(动态模式), 灵活的文档模型

 

基本常用命令

数据库操作

默认保留的数据库

admin: ,被添加到root数据库的用户自动继承所有数据库的权限, 一些特定的服务器端命令也只能从这个数据库运行, 比如列出所有的数据库或者关闭服务器

local: 数据永远不会被复制, 用来存储限于本地的单台服务器的集合 (部署集群, 分片等)

config: Mongo用于分片设置时, config数据库在内部使用, 用来保存分片的相关信息

 

文档基本 CRUD

创建 Create

db.<collection_name>.insertOne() 向集合中添加一个文档, 参数一个json 格式的文档

db.<collection_name>.insertMany() 向集合中添加多个文档, 参数为 json 文档数组

db.collection.insert({

  <document or array of documents>,

  writeConcern: <document>,

  ordered: <boolean>

})

// 向集合中添加一个文档

db.collection.insertOne(

   { item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } }

)

// 向集合中添加多个文档

db.collection.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" } },

])

注:向 collection 中插入 document 文档时, 如果没有给文档指定 _id 属性, 数据库会为文档自动添加 _id field, 并且值类型是 ObjectId(blablabla), 就是文档的唯一标识。

 

mongo 中的数字, 默认情况下是 double 类型, 如果要存整型, 必须使用函数NumberInt(整型数字), 否则取出来就有问题。

插入当前日期可以使用 new Date()

 

如果某条数据插入失败, 将会终止插入, 但已经插入成功的数据不会回滚掉.  可以使用 try catch 进行异常捕捉处理, 测试的时候可以不处理.如:

try {

db.comment.insertMany([

{……}{……}

]);

} catch (e) {

  print (e);

}

 

查询 Read

db.<collection_name>.find() 接受一个 json 格式的查询条件. 返回一个数组

db.<collection_name>.findOne() 查询集合中符合条件的第一个文档, 返回一个对象

操作符:

在 terminal 中查看结果可能不是很方便,可用 pretty() 来帮助阅读

db.inventory.find().pretty()

匹配内容

db.posts.find({

  comments: {

    $elemMatch: {

      user: 'Harry Potter'

    }

  }

}).pretty()

// 正则表达式

db.<collection_name>.find({ content : /once/ })

创建索引

db.posts.createIndex({

  { title : 'text' }

})

// 文本搜索

db.posts.find({

  $text : {

    $search : "\"Post O\""

  }

}).pretty()

 

更新 Update

db.<collection_name>.updateOne(<filter>, <update>, <options>) :修改一个匹配 <filter> 条件的文档

db.<collection_name>.updateMany(<filter>, <update>, <options>) :修改所有匹配 <filter> 条件的文档

db.<collection_name>.replaceOne(<filter>, <update>, <options>) :替换一个匹配 <filter> 条件的文档

db.<collection_name>.update(查询对象, 新对象):默认情况下会使用新对象替换旧对象

db.document.update({ userid: "30", { $set {username: "guest"} } })//默认修改第一条

db.document.update({ userid: "30", { $set {username: "guest"} } }, {multi: true})//修改所有符合条件的

其中 <filter> 参数与查询方法中的条件参数用法一致.

 

db.<collection_name>.replaceOne():替换除 _id 属性外的所有属性, 其<update>参数应为一个全新的文档.

db.inventory.replaceOne(

    { item: "paper" },

    { item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] }

)

删除delete

db.collection.deleteMany() :删除所有匹配的文档.

db.collection.deleteOne() :删除单个匹配的文档.

db.collection.drop()

db.dropDatabase()

db.inventory.deleteMany( { qty : { $lt : 50 } } )

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

一般数据库中的数据都不会真正意义上的删除, 会添加一个字段, 用来表示这个数据是否被删除

 

文档排序 Sort

查询文档内容时, 默认是按照 _id 进行排序,可用 $sort 更改文档排序规则

{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }

对于要排序的字段,请将排序顺序设置为1或-1,以分别指定升序或降序排序

db.users.aggregate(

   [

     { $sort : { age : -1, posts: 1 } }

   ]

)

 

$sort运算符和内存

$sort + $limit 内存优化

当$sort在$limit之前,并且没有修改文档数量的中间阶段时,优化器可以将$limits合并为$sort。这允许$sort操作在进行过程中只维护前n个结果(n是指定的限制),并确保MongoDB只需要在内存中存储n个项目。当allowDiskUse为true且n项超过聚合内存限制时,此优化仍然适用。

优化可能会在不同版本之间发生变化。

 

投影 Projection

对文档进行查询并不是需要所有的字段,可对文档进行“投影”

1 - display

0 - dont display

> db.users.find( {}, {username: 1} )

> db.users.find( {}, {age: 1, _id: 0} )

forEach()

> db.posts.find().forEach(fucntion(doc) { print('Blog Post: ' + doc.title) })

正则表达式

$ db.collection.find({field:/正则表达式/})

$ db.collection.find({字段:/正则表达式/})

比较查询

<, <=, >, >= :

db.collection.find({ "field" : { $gt: value }}) //大于: field > value

db.collection.find({ "field" : { $lt: value }}) //小于: field < value

db.collection.find({ "field" : { $gte: value }}) //大于等于: field >= value

db.collection.find({ "field" : { $lte: value }}) //小于等于: field <= value

db.collection.find({ "field" : { $ne: value }}) //不等于: field != value

包含查询

包含: $in 操作符. db.comment.find({userid:{$in:["1003","1004"]}})

不包含: $nin 操作符. db.comment.find({userid:{$nin:["1003","1004"]}})

 

常用命令小结

选择切换数据库:use articledb

插入数据:db.comment.insert({bson数据})

查询所有数据:db.comment.find();

条件查询数据:db.comment.find({条件})

查询符合条件的第一条记录:db.comment.findOne({条件})

查询符合条件的前几条记录:db.comment.find({条件}).limit(条数)

查询符合条件的跳过的记录:db.comment.find({条件}).skip(条数)

修改数据:db.comment.update({条件},{修改后的数据})

        或db.comment.update({条件},{$set:{要修改部分的字段:数据})

修改数据并自增某字段值:db.comment.update({条件},{$inc:{自增的字段:步进值}})

删除数据:db.comment.remove({条件})

统计查询:db.comment.count({条件})

模糊查询:db.comment.find({字段名:/正则表达式/})

条件比较运算:db.comment.find({字段名:{$gt:值}})

包含查询:db.comment.find({字段名:{$in:[值1, 值2]}})

        或db.comment.find({字段名:{$nin:[值1, 值2]}})

条件连接查询:db.comment.find({$and:[{条件1},{条件2}]})

           或 db.comment.find({$or:[{条件1},{条件2}]})

 

文档间的对应关系:一对一、一对多、多对多

 

MongoDB 的索引

MongoDB 可使用索引限制必须检查的文档数.

MongoDB 使用的是 B Tree, MySQL 使用的是 B+ Tree

db.<collection_name>.createIndex({ userid : 1, username : -1 })

db.<collection_name>.getIndexes()

db.<collection_name>.dropIndex(index)

db.<collection_name>.dropIndex( "userid_1_username_-1" )

db.<collection_name>.dropIndex({ userid : 1, username : -1 })

db.<collection_name>.dropIndexes()

 

索引的类型:

单字段索引 Single Field Index

复合索引 Compound Index

地理空间索引(Geospatial Index):返回结果时使用平面几何的二维索引、使用球面几何的二维球面索引

文本索引(Text Indexes):支持在集合中搜索字符串内容.这些文本索引不存储特定于语言的停止词(例如 “the”), 而将集合中的词作为词干, 只存储根词.

哈希索引(Hashed Indexes):为了支持基于散列的分片, MongoDB 提供了散列索引类型, 它对字段值的散列进行索引.这些索引在其范围内的值分布更加随机, 但只支持相等匹配, 不支持基于范围的查询.

 

索引的查看:db.collection.getIndexes()

默认 _id 索引: MongoDB 在创建集合的过程中, 在 _id 字段上创建一个唯一的索引, 默认名字为 _id , 该索引可防止客户端插入两个具有相同值的文档.

该索引是唯一索引, 因此值不能重复, 即 _id 值不能重复的.

在分片集群中, 通常使用 _id 作为片键.

 

索引的创建:db.collection.createIndex(keys, options)

参数

Parameter

Type

Description

keys

document

包含字段和值对的文档。字段是索引键,值描述该字段的索引类型。升序:1;降序:-1。如:({字段:1或-1}。MongoDB支持不同的索引类型:文本、地理空间和哈希索引。

options

document

可选。包含一组控制索引创建的选项的文档。

 

注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex() , 之后的版本使用了 db.collection.createIndex() 方法, ensureIndex() 还能用, 但只是 createIndex() 的别名.

 

索引的删除

# 删除某一个索引:$ db.collection.dropIndex(index)

# 删除全部索引:$ db.collection.dropIndexes()

 

索引使用

执行计划

分析查询性能 (Analyze Query Performance) 通常用执行计划 (解释计划 - Explain Plan) 来查看查询的情况

$ db.<collection_name>.find( query, options ).explain(options)

比如: 查看根据 user_id 查询数据的情况

"stage" : "COLLSCAN", 表示全集合扫描

"stage" : "IXSCAN", 基于索引的扫描

 

涵盖的查询

当查询条件和查询的投影仅包含索引字段时, MongoDB 直接从索引返回结果, 而不扫描任何文档或将文档带入内存, 这些覆盖的查询十分有效。

 

 


MongoDB基础的评论 (共 条)

分享到微博请遵守国家法律