mongodb知识点整理

一、 安装

下载地址:https://www.mongodb.com/try/download/community

1、Windows安装配置

下载:mongodb-windows-x86_64-4.4.12.zip
解压:D:\penngo\mongodb-4.4.12
新建文件夹data,
D:\penngo\mongodb-4.4.12\data
新建配置文件
D:\penngo\mongodb-4.4.12\mongo.conf

# 数据库文件路径
dbpath=D:\penngo\mongodb-4.4.12\data
# 日志文件
logpath=D:\penngo\mongodb-4.4.12\mongo.log
# 日志采用追加模式,配置后mongodb日志会追加到现有的日志文件
#logappend=true
# 端口号 默认为 27017
port=27017
#指定mongodb使用内存的多少4G
#storage.wiredTiger.engineConfig.cacheSizeGB=4

启动命令

mongod --config ../mongo.conf

作为windows服务启动

mongod --config "D:\penngo\mongodb-4.4.12\mongo.conf" --install --serviceName "MongoDB"

2、服务器端启动

Unix 命令行:

$ mongod

Windows 命令行:

> mongod.exe

如果省略参数, mongod默认的使用数/data/db/(Windows为当前盘的 \data\db\)。因此在启动之前,需要创建数据目录(如 mkdir -p /data/db/),并且对该目录有写权限。

二、基本术语和概念

1、下表介绍了各种SQL和MongoDB对比的术语和概念

SQL术语/概念MongoDB 术语/概念
数据库(database)数据库(database)
表(table)集合(collection)
行(row)文档(document or BSON document)
列(column)字段(field)
索引(index)索引(index)
表连接(table joins)多表关联,内嵌文档($lookup, embedded documents)
主键(primary key)可以指定一列或多列作为主键 主键(primary key)
MongoDB默认以 _id字段为主键.
聚合,列如group by(aggregation (e.g. group by))聚合管道(aggregation pipeline)See the SQL to Aggregation Mapping Chart.
将一个表中的数据插入到另一个表(SELECT INTO NEW_TABLE)$out操作
查看 SQL to Aggregation Mapping Chart.
合并更新(MERGE INTO TABLE)$merge (MongoDB 4.2可用)
查看 SQL to Aggregation Mapping Chart.
合并查询(UNION ALL)$unionWith ( MongoDB 4.4可用)
事务(transactions)事务(transactions)
注意:在许多场景下,应该使用合适的建模(例如内嵌文档或数组)来减少多文档事务的需求。

2、下表是部分数据库与MongoDB可运行程序名称的对比

MongoDBMySQLOracleInformixDB2
服务器端程序mongodmysqldoracleIDSDB2
客户端程序mongoshmysqlsqlplusDB-AccessDB2 Client

3、MongoDB保留的数据库名称

admin:数据库会在身份验证和授权时被使用,某些管理操作也需要访问此数据库。
local:在副本集中,local 用于存储复制过程中所使用的数据,而 local 数据库本身不会被复制。
config:在分片集群会使用config数据库存储每个分片的信息。

4、数据类型

JSON数据格式支持有6 种数据类型,MongoDB 在JSON的基础上,增加了其它数据类型的支持。
null
null 类型用于表示空值或不存在的字段。
布尔类型
布尔类型的值可以为 true 或者 false。
数值类型
shell 默认使用 64 位的浮点数来表示数值类型。
{“x” : 3.14}
{“x” : 3}
对于整数,可以使用 NumberInt 或 NumberLong 类,它们分别表示 4 字节和 8 字节的有符号整数。
{“x” : NumberInt(“3”)}
{“x” : NumberLong(“3”)}
字符串类型
任何 UTF-8 字符串都可以使用字符串类型来表示。
{“x” : “foobar”}
日期类型
MongoDB 会将日期存储为 64 位整数,表示自 Unix 纪元(1970年 1 月 1 日)以来的毫秒数,不包含时区信息。
{“x” : new Date()}
正则表达式
查询时可以使用正则表达式,语法与 JavaScript 的正则表达式语法相同。
{“x” : /foobar/i}
数组类型
集合或者列表可以表示为数组。
{“x” : [“a”, “b”, “c”]}
内嵌文档
文档可以嵌套其他文档,此时被嵌套的文档就成了父文档的值。
{“x” : {“foo” : “bar”}}
Object ID
Object ID 是一个 12 字节的 ID,是文档的唯一标识。
{“x” : ObjectId()}
二进制数据
二进制数据是任意长度的字符串,不能通过 shell 操作。如果要将非 UTF-8 字符串存入数据库,那么使用二进制数据是唯一的方法。
代码
可以在查询和文档中存储任意的 JavaScript 代码:
{“x” : function() { /* … */ }}

三、MongoDB shell

mongo shell 是一个管理 MongoDB 实例和操作数据的命令行工具,同时是一个功能齐全的 JavaScript 解释器,能够运行任意的JavaScript 程序。

1、连接服务器

连接mongod服务器,需要指定主机名、端口和数据库,如果缺少这三个参数,默认连接本机服务器:

$ mongo host:27017/myDB

使用 --nodb 参数,不连接数据库:

$ mongo –nodb

可以在启动之后,再连接到mongod:

> conn = new Mongo("some-host:30000")
connection to some-host:30000
> db = conn.getDB("myDB")
myDB

2、使用帮助

内置了帮助文档,可以输入 help 命令查看:

> help
db.help() 查看数据库级别的帮助信息.
db.foo.help() 查看集合级别的帮助信息。

3、执行基本的Javascript

3.1、执行基本的数学运算

> x = 200;
> x / 5;

3.2、使用JavaScript 标准库

> Math.sin(Math.PI / 2);
> new Date("2019/1/1");
> "Hello, World!".replace("World", "MongoDB");

3.3、使用JavaScript 函数

> function factorial (n) {
... if (n <= 1) return 1;
... return n * factorial(n - 1);
... }
> factorial(5);
120

3.4、打印函数源代码

> db.movies.updateOne

3.5、执行JavaScript文件

 $ mongo script1.js script2.js

如果需要在远程主机运行脚本,则需要先指定地址,之后再指定脚本:

$ mongo server-1:30000/foo --quiet script1.js script2.js

3.6、用load 函数先加载,再从交互式shell中运行脚本

> load("script1.js")
I am script1.js
true
>

3.7、shell辅助函数对应的JavaScript函数

辅助函数等价函数
use videodb.getSisterDB(“video”)
show dbsdb.getMongo().getDBs()
show collectionsdb.getCollectionNames()

3.8、可以定义函数变量,例如defineConnectTo.js

var connectTo = function(port, dbname) {
 if (!port) {
 port = 27017;
 }
 if (!dbname) {
 dbname = "test";
 }
 db = connect("localhost:"+port+"/"+dbname);
 return db;
};

在shell 中加载defineConnectTo.js,connectTo 函数就可以使用了:

> load('defineConnectTo.js')
> typeof connectTo
function

四、创建、更新和删除文档

1、插入文档

insertOne 插入单个文档,文档自动添加一个 “_id” 键:

> db.movies.insertOne({"title" : "Stand by Me"})

insertMany插入多个文档

db.movies.insertMany([{"title" : "Ghostbusters"},{"title" : "E.T."}]);

insertMany批量插入文档会明显提高插入的速度。
从3.2 开始, shell 支持insertOne 和 insertMany 以及其他一些方法。insert 等方法仍然向后兼容,但不建议继续使用。

2、删除文档

deleteOne 将删除满足条件的第一个文档。
deleteMany 来删除满足筛选条件的所有文档。
drop清空整个集合,使用 drop 直接删除集合,然后在这个空集合中重建各项索引会更快:

> db.movies.drop()

从3.2 开始,shell支持deleteOne 和deleteMany这些方法。remove 仍可使用,但不推荐。

3、更新文档

updateOne、updateMany 和 replaceOne。
replaceOne 会用新文档完全替换匹配的文档。

“$set” 设置字段的值。

db.users.updateOne({"name" : "joe"},{"$set" : {"favorite book" :["Cat's Cradle", "Foundation Trilogy"]}})

“$unset” 删除字段:

db.users.updateOne({"name" : "joe"},{"$unset" : {"favorite book" : 1}})

“$inc” 自增和自减,只能用于整型、长整型或双精度浮点型:

db.users.updateOne({"game" : "pinball", "user" : "joe"}, {"$inc" : {"score" : 50}})

“$push” 给数组添加元素,默认添加在尾部,不存在则创建新的数组

db.blog.posts.updateOne({"title" : "A blog post"},{"$push" : {"comments" :{"name" : "joe", "email" : "joe@example.com", "content" : "nice post."}}})

“$each” 可以对 “$push” 使用"$each" 修饰符,在一次操作中添加多个值:

db.stock.updateOne({"_id" : "GOOG"}, {"$push" : {"hourly" : {"$each" : [562.776, 562.790,559.123]}}})

“$slice” 配合 $push 设置数组长度:

db.movies.updateOne({"genre" : "horror"},{"$push" : {"top10" : {"$each" : ["hell1", "hell2",...],"$slice" : -10}}})

这个例子限制了数组只包含最后加入的 10 个元素。
“$sort” 可以将 “$sort” 修饰符应用于 “$push” 操作:

> db.movies.updateOne({"genre" : "horror"},{"$push" : {"top10" : {"$each" : [{"name" : "hello1","rating" : 6.6},{"name" : "hello2","rating" : 4.3},...], "$slice" : -10, "$sort" : {"rating" : -1}}}})

根据 “rating"值对数组中进行排序,只保留前 10 个。注意,不能只将 “$slice” 或”$sort" 与 “$push” 配合使用,必须包含 “$each”。
“$ne”“$addToSet” :将数组作为集合使用,仅当一个值不存在时才进行添加。

 > db.book.updateOne({"authors cited" : {"$ne" :"Richie"}},{$push : {"authors cited" : "Richie"}})
 >db.users.updateOne({"_id" :ObjectId("4b2d75476cc613d5ee930164")},{"$addToSet" : {"emails" : "joe@gmail.com"}})

还可以将 “$addToSet”“$each” 结合使用,以添加多个不同的值,而这不能使用 “$ne”“$push” 的组合来实现。

 >db.users.updateOne({"_id" :ObjectId("4b2d75476cc613d5ee930164")},{"$addToSet" : {"emails" : {"$each" :["joe@php.net","joe@example.com","joe@python.org"]}}})

“$pop” 删除元素。。

{"\$pop" : {"key" : 1}} 从尾部删除一个元素,
{"\$pop" : {"key" : -1}}从头部删除一个元素。

“$pull” 删除符合条件的所有数组元素。

> db.lists.updateOne({}, {"$pull" : {"todo" : "laundry"}})

“$” 定位运算符,它可以计算出查询文档匹配的数组元素并更新该元素。

> db.blog.updateOne({"comments.author" : "John"}, {"$set" : {"comments.$.author" : "Jim"}})

“arrayFilters”:此选项使我们能够修改与特定条件匹配的数组元素。

db.blog.updateOne({"post" : post_id },{ $set: { "comments.$[elem].hidden" : true } },{arrayFilters: [ { "elem.votes": { $lte: -5 } }]})

**“upsert”**如果找不到,则创建一个新文档;如果找到了匹配的文档,则进行正常的更新。

> db.analytics.updateOne({"url" : "/blog"}, {"$inc" :{"pageviews" : 1}},{"upsert" : true})

“save” shell 函数
在文档不存在时插入文档,在文档存在时更新文档。

> var x = db.score.findOne()
> x.num = 42
42
> db.score.save(x)

updateManyupdateOne接受相同的参数,区别在于被更改的文档数量。

> db.users.updateMany({"birthday" : "10/13/1978"}, {"$set" : {"gift" : "Happy Birthday!"}})

3.2 版本中 shell 引入了 3 个新的集合方法来提供findAndModify 的功能:findOneAndDeletefindOneAndReplacefindOneAndUpdate。与 updateOne 的区别在于,可以返回修改后的值。
findOneAndUpdate:4.2增加用来更新的聚合管道。管道可以包含以下操作:$addFields 及其别名 (别名$set)、$project(别名$unset),以及 $replaceRoot(别名$replaceWith)。

> db.processes.findOneAndUpdate({"status" : "READY"}, {"$set" : {"status" : "RUNNING"}},{"sort" : {"priority" : -1}})

返回修改后的值

> db.processes.findOneAndUpdate({"status" : "READY"},{"$set" : {"status" : "RUNNING"}},{"sort" : {"priority" : -1},"returnNewDocument": true})

findOneAndReplace:接受相同的参数,并根据 returnNewDocument 选项的值,返回替换之前或之后的文档。
findOneAndDelete:与上边类似,只是返回被删除的文档。

五、查询

1、find和findOne

find和findOne使用相同的参数,find返回多条文档,findOne返回一条文档。

查询文档中添加键–值对时,就意味着限定了查询条件。

> db.users.find({"username" : "joe", "age" : 27})

指定要返回的字段

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

剔除某些字段

> db.users.find({}, {"fatal_weakness" : 0})

2、查询条件

2.1、查询条件

“$lt”、“$lte”、“$gt” 和 “$gte” 都属于比较运算符,分别对应 <、<=、> 和 >=。可以将它们组合使用以查找一个范围内的值。

> db.users.find({"age" : {"$gte" : 18, "$lte" : 30}})

条件运算符 “$ne” 了,它表示“不相等”。

> db.users.find({"username" : {"$ne" : "joe"}})

2.2、OR查询

两种方式可以进行 OR 查询。“$in” 和"$or" 。

> db.raffle.find({"ticket_no" : {"$in" : [725, 542, 390]}})
> db.raffle.find({"$or" : [{"ticket_no" : 725}, {"winner" :true}]})

与 “$in” 相反的是 “$nin”

> db.raffle.find({"ticket_no" : {"$nin" : [725, 542, 390]}})

“$or” 可以包含其他条件。

> db.raffle.find({"$or" : [{"ticket_no" : {"$in" : [725, 542,390]}}, {"winner" : true}]})

2.3、$not

取模运算符 “$mod” ,“$mod” 会将查询的值除以第一个给定值,如果余数等于第二个给定值,则匹配成功:

> db.users.find({"id_num" : {"$mod" : [5, 1]}})

“$not” 是一个元条件运算符:可以用于任何其他条件之上。

> db.users.find({"id_num" : {"$not" : {"$mod" : [5, 1]}}})

3、特定类型的查询

3.1、null

查询 “y” 键为 null 的文档,还会返回缺少这个键的所有文档

> db.c.find({"y" : null})

如果仅想匹配键值为 null 的文档,则需要检查该键的值是否为null,并且通过 “$exists” 条件确认该键已存在。

> db.c.find({"z" : {"$eq" : null, "$exists" : true}})

3.2、正则表达式

“$regex” 可以在查询中为字符串的模式匹配提供正则表达式功能。
用户名为 Joe 或 joe 的用户,那么可以使用正则表达式进行不区分大小写的匹配:

> db.users.find( {"name" : {"$regex" : /joe/i } })

如果除了匹配各种大小写组合形式的“joe”之外,还希望匹配如“joey”这样的键,那么可以改进一下刚刚的正则表达式:

> db.users.find({"name" : /joey?/i})

3.3、查询数组

01. “$all”
“$all” 查询来找到同时包含元素 “apple” 和"banana" 的文档

db.food.find({fruit : {KaTeX parse error: Expected 'EOF', got '}' at position 26: …ple", "banana"]}̲}) 在数组中查询特定位置的元…size"**
KaTeX parse error: Expected '}', got 'EOF' at end of input: …d({"fruit" : {"size” : 3}})
03. “$slice”
find 的第二个参数是可选的,可以指定需要返回的键。
返回前 10 条评论:

> db.blog.posts.findOne({}, {"comments" : {"$slice" :10}})

返回后 10 条评论,则可以使用 -10:

> db.blog.posts.findOne({}, {"comments" : {"$slice" :-10}})

“$slice” 也可以指定偏移量和返回的元素数量来获取数组中间的结果,例如返回第 24~33 个元素。

> db.blog.posts.findOne(criteria, {"comments" : {"$slice" :[23, 10]}})

使用 “$slice” 来获取最后一条评论,如下所示:

> db.blog.posts.findOne(criteria, {"comments" : {"$slice" :-1}})

04. 返回一个匹配的数组元素
可以使用$ 运算符来返回匹配的元素。

> db.blog.posts.find({"comments.name" : "bob"},{"comments.$" : 1})

05. 数组与范围查询的相互作用
如 “x” 必须同时满足大于 10 且小于 20

> db.test.find({"x" : {"$gt" : 10, "$lt" : 20}})

可以使用min 和 max 将查询条件遍历的索引范围限制为 “ g t " 和 " gt" 和" gt""lt” 的值:

> db.test.find({"x" : {"$gt" : 10, "$lt" : 20}}).min({"x" :10}).max({"x" : 20})

3.4、查询内嵌文档

查询内嵌文档的方法有两种:查询整个文档或针对其单个键–值对进行查询。

{
 "name" : {
 "first" : "Joe",
 "last" : "Schmoe"
 },
 "age" : 45
}

查询整个内嵌文档的工作方式与普通查询相同。

> db.people.find({"name" : {"first" : "Joe", "last" :"Schmoe"}})

针对内嵌文档的特定键进行查询。

> db.people.find({"name.first" : "Joe", "name.last" : "Schmoe"})

4、$where查询

“$where” 子句,可以使用JavaScript 代码。

db.foo.find({"KaTeX parse error: Expected '}', got '&' at position 102: …rrent != other &̲& this[current]…where"比常规查询慢得多,并且BSON 转换为 JavaScript 对象,然后通过 “$where” 表达式运行,此外也无法使用索引。
3.6 增加了 $expr 运算符,它允许在查询语句中使用聚合表达式。因为它不需要执行 JavaScript,所以速度比 $where 快,建议尽可能使用此运算符作为替代。

5、游标

调用 find 时,shell 并不会立即查询数据库,而是等到真正开始请求结果时才发送查询,这样可以在执行之前给查询附加额外的选项。

> var cursor = db.foo.find().sort({"x" : 1}).limit(1).skip(10);
> var cursor = db.foo.find().limit(1).sort({"x" : 1}).skip(10);
> var cursor = db.foo.find().skip(10).limit(1).sort({"x" : 1});

要遍历结果,可以在游标上使用 next 方法。可以使用 hasNext 检查是否还有其他结果。

> while (cursor.hasNext()) {
 obj = cursor.next();
... 
}

六、索引

1、索引操作

创建 db.collection.createIndex(keys, options)
查看 db.collection.getIndexes()
删除某条 db.collection.dropIndex()
删除全部 db.collection.dropIndexes()

1.1、创建索引

db.users.createIndex({“firstname” : 1},{“name”:“index_firstname”, “unique” : true, “sparse”:true, “partialFilterExpression”:{“firstname”: {$exists: true } } } )

参数说明
unique:Boolean,建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name: string,索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
partialFilterExpression :Boolean,部分索引提供了稀疏索引功能的超集,使用一个文档来表示希望在其上创建索引的过滤器表达式。
MongoDB 4.2 引入了混合索引创建。它只在索引创建的开始和结束时持有排他锁,创建过程的其余部分会交错地让步于读写操作。

1.2、查询语句中加上explain,检查索引是否命中

db.users.find({“username”:“user101”}).explain(“executionStats”)
使用索引可以显著缩短查询时间,但是修改索引字段的写操作(插入、更新和删除)会花费更长的时间。因为在更改数据时,除了更新文档,MongoDB 还必须更新索引。

1.3、优化策略

(1)等值过滤的键应该在最前面;
(2)用于排序的键应该在多值字段之前;
(3)多值过滤的键应该在最后面;比如{age:15,score:{ l t : 70 , lt:70, lt:70,gt:60}}
(4)选择键的方向,使用与排序方向一样的索引。
(5)使用覆盖查询
如果查询只需要查找索引中包含的字段,那就没有必要去获取实际的文档了。
(6)隐式索引,复合索引具有“双重功能”,而且针对不同的查询可以充当不同的索引。
比如索引{name:1,age:1,score:1}
可以用在{name:usser001}条件查询,也可以用{name:user002,age:15}条件查询

七、特殊的索引和集合类型

1、地理空间索引

MongoDB 中对经纬度的存储有两种方式,分别是 Legacy Coordinate Pairs和 GeoJSON 。

1.1、Legacy Coordinate Pairs格式

数组形式:
{loc:[40.739037, 73.992964]}
嵌入文档形式
{loc:{lon:40.739037,lat:73.992964}}

1.2、GeoJSON格式

点格式
{“geometry1”: {
“type”: “Point”,
“coordinates”: [125.6, 10.1]
}}
线格式
{“geometry2”: {
“type”: “LineString”,
“coordinates”: [[125.6, 10.1],[125.6,10.2],[125.6,10.3]]
}}
多边形格式
{“geometry3”: {
“type”: “Polygon”,
“coordinates”: [[125.6, 10.1],[125.5,10.2],[125.7,10.3]]
}}
geometry名字可以随便取,但是内部字段固定。

1.3、地理空间查询

交集(“$geoIntersects”)、包含(“$geoWithin”)和接近( “$geoNear”)。
MongoDB 支持的查询类型和几何类型

查询类型几何类型
$near(GeoJSON 坐标,2dsphere 索引)球面
$near(遗留坐标,2d 索引)平面
$geoNear(GeoJSON 坐标,2dsphere 索引)球面
$geoNear(遗留坐标,2d 索引)平面
$nearSphere(GeoJSON 坐标,2dsphere 索引)球面
$nearSphere(遗留坐标,2d 索引)a球面
$geoWithin : { $geometry: … }球面
$geoWithin : { $box: … }平面
$geoWithin : { $polygon: … }平面
$geoWithin : { $center: … }平面
$geoWithin : { $centerSphere: … }球面
$geoIntersects球面

创建球面 2dsphere 索引

> db.neighborhoods.createIndex({geometry:"2dsphere"})

创建平面2d索引

> db.hyrule.createIndex({"loc" : "2d"})
1.3.1、根据坐标查找所处街区

db.locations.findOne({geometry:{KaTeX parse error: Expected '}', got 'EOF' at end of input: …eoIntersects: {geometry:{type:“Point”,coordinates:[-75.93414657,41.82302903]}}}})

1.3.2、查找区域内所有人

db.users.find(
{location: {KaTeX parse error: Expected '}', got 'EOF' at end of input: geoWithin: {geometry: neighborhood.geometry3}}},
{username: 1, _id: 0}
);

1.3.3、返回指定距离内的人(无序)
> db.users.find({location: {$geoWithin: {$centerSphere: [[-73.93414657,40.82302903],5/3963.2]}}})

“$centerSphere” 的第二个参数会接受以弧度表示的半径。该查询通过除以长度大约为 3963.2 英里的地球赤道半径将距离转换为弧度。

db.restaurants.find({location: {$nearSphere: {$geometry: {type: "Point",coordinates:[-73.93414657,40.82302903]},$maxDistance: 5*1609.34}}});

使用 “$nearSphere” 并指定一个以米为单位的**“$maxDistance”**。这样做会返回距离用户 5 英里内的所有用户,并按由近到远的顺序进行排序。

2、全文搜索索引

全文索引使用 Apache Lucene 来提供搜索功能,与普通的文本索引不同
创建 “title” 字段和 “body” 字段索引:

> db.collection1.createIndex({"title": "text","body" : "text"})

也可以为每个字段指定权重:

> db.collection1.createIndex({"title": "text","body": "text"},{"weights" : {"title" : 3,"body" : 2}})

对所有字段设置全文索引

> db.collection1.createIndex({"$**" : "text"})

查询的时候使用text索引

db.collection1.find({$text: { $search: inputValue}})

计算文档得分,存储在textScore,并按分值排序

db.collection1.find({$text: { $search: inputValue}}, {score: {$meta: "textScore"}}).sort({ score:{$meta: "textScore"} })

关于全文索引的基本知识点
(1)text索引只能创建于类型为string或者string类型数组的字段
(2)双引号表示与,比如 { $text: { $search: “\“coffee shop\”” } } 表示同时包含coffee和shop
(3)没有双引号只有空格表示或, 比如 { $text: { $search: “coffee shop” } 表示包含coffee 或者 shop
(4)不包含用减号, 比如 { $text: { $search: “shop -coffee” } } 表示包含shop但是不包含coffee

默认为英语,可以设置为其它语言

> db.users.createIndex({"profil" : "text","intérêts" : "text"},{"default_language" : "french"})

当前支持的语言

Language NameISO 639-1 (Two letter codes)
danishda
dutchnl
englishen
finnishfi
frenchfr
germande
hungarianhu
italianit
norwegiannb
portuguesept
romanianro
russianru
spanishes
swedishsv
turkishtr
对于暂不支持的语言,全文索引将用使用简单的停用词来词,比如中文,会使用空格或符号来分词

3、固定集合

固定集合指的是事先创建而且大小固定的集合,固定集合很像队列,如果空间不足,最早的文档就会被删除。
优点
(1).写入速度更快。
(2).固定集合会自动覆盖掉最老的文档。
应用场景
日志文件,聊天记录,通话信息记录,固定长度的推荐文章等,只保存一定大小的历史记录,过期的则会进行删除!

固定集合需要先创建才能使用
例如,创建固定集合coll_penngo,空间大小限制为100000个字节。

db.createCollection("coll_penngo",{capped:true,size:100000});

除了空间大小,还可以指定文档的数据量大小。
例如,创建固定集合coll_penngo,空间大小为100000个字节,文档数量大小为100条记录。

db.createCollection("coll_penngo",{capped:true,size:100000,max:100});

可以将普通集合装换为固定集合,使用的命令是 convertToCapped。
例如将testcol1集合转换为一个大小为1024字节的固定集合:
db.runCommand({“convertToCapped”:“testcollection”,“size”:100000})

固定集合信息的查看
(1)判断集合是否为固定集合:
db.coll_penngo.isCapped()。

(2)从集合信息中获取有关固定集合的属性:
db.coll_penngo.stats()

注意事项:
(1)固定集合的文档不能删除,但是可以删除整个集合。对固定集合中的文档可以进行更新或替换操作,如果大于限定的空间和数量,都会失败。
(2)普通集合可以使用 convertToCapped转换固定集合,但是固定集合不可以转换为普通集合。使用普通集合转换固定集合时,原有的索引会丢失,需要重新创建。
(3)创建固定集合,为固定集合指定文档数量限制时(指参数max),必须同时指定固定集合的空间大小(指参数size)。对集合估算size时,不要依据集合的storageSize ,而是依据集合的size。storageSize是wiredTiger存储引擎采用高压缩算法压缩后的。不管先达到哪一个限制,之后插入的新文档都会把最老的文档移除集合。
(4)固定集合不能分片。

可追加游标
在访问固定集合的结果集,可以使用可追加游标,当结果遍历完,游标不关闭,继续等待新数据。mongo shell 不允许可追加游标,PHP 中使用可追加游标的例子:

$cursor = $collection->find([], [
 'cursorType' => MongoDB\Operation\Find::TAILABLE_AWAIT,
 'maxAwaitTimeMS' => 100,
]);
while (true) {
 if ($iterator->valid()) {
 $document = $iterator->current();
 printf("penngo固定集合: %s\n", $document-
>createdAt);
 }
 $iterator->next();
}

这个游标不会自己关闭,直到游标超时功人为中止。

4、TTL索引

TTL索引介绍
TTL全称是(Time To Live),TTL索引可以设置数据的有效时间,自动删除过期的数据,可以在对字段创建索引时添加expireAfterSeconds参数将索引转换为TTL索引,该字段必需是date类型,在以下几种场景下即使索引设置了expireAfterSeconds属性也不会生效

  • 如果该字段不是date类型,则文档不会过期
  • 如果文档没包含索引的这个字段,则文档不会过期

TTL索引运行逻辑
MongoDB会开启一个后台线程来判断该TTL索引的值是否过期,不过并不能保证已过期的数据会立即被删除,因为后台线程每60秒触发一次删除任务,如果删除的数据量较大,存在删除不完,保留超过60秒以上的情况。
对于副本集而言,TTL索引的后台进程只会在primary节点开启,在从节点会始终处于空闲状态,从节点的数据删除是由主库删除后产生的oplog来做同步。
TTL索引除了有expireAfterSeconds属性外,和普通索引一样。

TTL索引的使用场景
(1)指定具体的过期时间属性
该场景是在创建索引时明确指定一个expireAfterSeconds时间作为文档的过期时间
// 对log_events集合的createdAt字段创建TTL索引且设置expireAfterSeconds过期时间为3600秒(1小时)
db.log_events.createIndex( { “createdAt”: 1 }, { expireAfterSeconds: 3600 } )
//文档插入数据,包含createdAt字段,则该文档会在1小时候后删除

(2)插入一个具体的过期时间
在创建索引时将expireAfterSeconds设置为0,在这种情况下由插入到字段的数据来控制文档何时过期,这种场景更加精细化,可灵活的控制文档的过期时间及控制在业务低峰期触发文档过期
// 对log_events集合的expireAt创建TTL索引,并设置expireAfterSeconds属性为0

db.log_events.createIndex( { “expireAt”: 1 }, { expireAfterSeconds: 0 } )
// 对文档插入数据,包含expireAt字段,该文档过期时间就是expireAt字段记录的时间
db.log_events.insert({“expireAt”: new Date(‘2022-09-01 00:00:00’),“logEvent”: 2,})

(3)TTL属性的修改(collMod)
对于TTL索引的expireAfterSeconds的属性,可以用collMod方式进行修改,修改索引定义,将一小时文档过期改为60秒
db.runCommand( { collMod: “log_events”,index: { keyPattern: { createdAt: 1 },expireAfterSeconds: 60}})

5、使用GridFS存储文件

mongoDB除了保存各种文档(JOSN结构)外还能够保存文件。GridFS规范提供了一种透明机制,可以将一个大文件分割成为多个较小的文档,这样的机制允许我们有效的保存大文件对象,特别对于那些巨大的文件,比如视频、高清图片等。

GridFS使用两个集合(fs.files与fs.chunks)来存储数据:
fs.files:包含元数据对象
文件的元数据放在这个集合里面,默认fs.files。这个里面的每个文档表示GridFS中的一个文件,与文件相关的自定义元数据也保存在其中,除了用户自定义的键,GridFS还有默认的一些键:
_id:文件唯一的id,在块中为“files_id”键的值存储
length:文件内容总的字节数
chunksize:每块的大小,以字节为单位。默认25K,可以调整
uploadDate:文件存入的时间
md5:文件内容的md5校验,由服务端生成
chunks:包含其他一些相关信息的二进制块

fs.chunks:块的集合。这个块集合的文档结构:
_id:标志唯一
n:表示块的编号,也就是这个块在原文件中的顺序号
data:包含组成文件块的二进制数据
files_id: 包含这个块元数据的文件文档的"_id"

mongofiles命令,可以用来在 GridFS 中上传文件、下载文件、查看文件列表、搜索文件,以及删除文件。
put:将文件系统中的一个文件添加到GridFS

mongofiles.exe put foo.txt  

list:会把所有添加到GridFS中的文件列出来

mongofiles.exe list  

get:put的反向操作

mongofiles.exe get foo.txt  

mongofiles 还支持另外两种操作:用于在 GridFS 中搜索文件的 search 操作和用于从GridFS 中删除文件的 delete 操作。

文章内容来自官网和网络整理
mongodb官网:https://www.mongodb.com/docs/manual/reference/

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MongoDB是一个开源的、跨平台的、面向文档的NoSQL数据库管理系统。它以JSON风格的文档存储数据,具有灵活的数据模型和强大的查询能力。以下是一些MongoDB知识点: 1. 数据模型:MongoDB使用BSON(二进制JSON)格式存储数据,可以存储复杂的数据结构,如嵌套文档和数组。每个文档都有一个唯一的_id字段作为主键。 2. 集合和文档:MongoDB将数据组织成集合(Collection),每个集合包含多个文档(Document)。文档类似于关系数据库中的行,但没有固定的模式。 3. 查询:MongoDB支持丰富的查询语法,包括比较、逻辑、正则表达式等操作符。可以使用find()方法进行查询,并可以使用索引来提高查询性能。 4. 索引:MongoDB支持创建索引来加速查询。常见的索引类型包括单字段索引、复合索引、文本索引等。可以使用ensureIndex()方法创建索引。 5. 聚合管道:MongoDB提供了聚合管道(Aggregation Pipeline)功能,可以对集合中的文档进行多阶段的数据处理和转换。 6. 复制和故障转移:MongoDB支持数据复制和故障转移,通过复制集(Replica Set)来提供数据的冗余和高可用性。 7. 分片:MongoDB支持数据分片(Sharding),可以将数据分散存储在多个服务器上,提高数据存储和查询的性能。 8. 安全性:MongoDB提供了访问控制、身份验证和加密等安全功能,可以保护数据的机密性和完整性。 以上只是MongoDB的一些基本知识点,还有更多高级的功能和特性可以进一步学习和探索。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

penngo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值