MongoDB【无敌详细,建议收藏】

"探索MongoDB的无边之境:沉浸式数据库之旅"

欢迎来到MongoDB的精彩世界!在这个博客中,我们将带您进入一个充满创新和无限潜力的数据库领域。无论您是开发者、数据工程师还是技术爱好者,MongoDB都将为您带来一场令人心动的沉浸式体验。

从一开始,我们将揭开MongoDB的神秘面纱,告诉您为什么它成为当今数据库领域的明星。您将发现MongoDB的灵活性和可扩展性如何颠覆传统数据库的概念,让您摆脱约束,以自由自在的方式处理数据。

在这个博客中,我们将带您深入了解MongoDB的架构和设计原理。您将探索文档型数据模型的魅力,学习如何利用无模式设计存储和查询各种类型的数据。我们还会分享一系列最佳实践、技巧和性能优化策略,让您的MongoDB应用发挥出最大的潜力。

不仅如此,我们将通过实际案例和故事,向您展示MongoDB如何在真实世界中发挥作用。您将了解到它如何助力起步公司快速迭代和扩展业务,如何帮助大型企业应对海量数据的挑战,以及如何在物联网和人工智能领域掀起革命性的变革。

无论您是MongoDB的新手还是有经验的专家,这个博客都将成为您掌握MongoDB的绝佳资源。加入我们,追寻MongoDB的无边之境,开启一段令人兴奋的数据库之旅吧!

基础知识

概述

MongoDB

简介
MongoDB是免费开源的跨平台NoSQL数据库,以BSON格式存储

BSON
BSON是一种类似于JSON的二进制形式的存储格式,简称Binary JSON
它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型
BSON有三个特点:轻量性、可遍历性、高效性

应用场景

适用场景
网站数据:Mongo 非常适合实时的插入,更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性
缓存:由于性能很高,Mongo 也适合作为信息基础设施的缓存层。在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数据源过载
大尺寸、低价值的数据:使用传统的关系型数据库存储一些大尺寸低价值数据时会比较浪费,在此之前,很多时候程序员往往会选择传统的文件进行存储
高伸缩性的场景:Mongo 非常适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持以及集群高可用的解决方案
用于对象及JSON数据的存储:Mongo的BSON数据格式非常适合文档化格式的存储及查询

具体应用
游戏场景:使用MongoDB存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景:使用MongoDB存储订单信息,订单状态在运送过程中会不断更新,以MongoDB内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来
社交场景:使用MongoDB存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景:使用MongoDB存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
直播:使用MongoDB存储用户信息、礼物信息等

逻辑结构

简介
MongoDB与MySQL中的架构相差不多,底层都使用了可插拔的存储引擎以满足用户的不同需要,用户可以根据程序的数据特征选择不同的存储引擎
在存储引擎上层的就是MongoDB的数据模型和查询语言

数据模型

简介
与SQL数据库不同,在SQL数据库中,在插入数据之前必须确定和声明表的架构
默认情况下,MongoDB的集合不要求其文档具有相同的架构

结构灵活
单个集合中的文档不需要具有相同的字段集合,并且集合中的文档之间的字段数据类型可能不同;
可灵活更改集合中文档的结构,如添加新字段、删除现有字段或将字段值更改为新类型,将文档更新为新结构。

文档结构【内嵌】
内嵌的方式指的是把相关联的数据保存在同一个文档结构之中
MongoDB的文档结构允许一个字段或者一个数组内的值作为一个嵌套的文档

文档结构【引用】
引用方式通过存储数据引用信息来实现两个不同文档之间的关联,应用程序可以通过解析这些数据引用来访问相关数据

WiredTiger存储引擎

简介
从MongoDB 3.2开始默认的存储引擎是WiredTiger,3.2版本之前的默认存储引擎是MMAPv1,MongoDB 4.x版本不再支持MMAPv1存储引擎
WiredTiger提供了不同粒度的并发控制和压缩机制,能够为不同种类的应用提供了最好的性能和存储率

支持document级别并发操作
WiredTiger对写入操作使用document级并发控制。因此,多个客户端可以同时修改集合的不同文档
对于大多数读写操作,WiredTiger使用乐观并发控制。WiredTiger仅在全局、数据库和集合级别使用意向锁
当存储引擎检测到两个操作之间的冲突时,其中一个操作将引发写入冲突,MongoDB会对用户透明地重试该操作

快照和检查点
WiredTiger使用多版本并发控制(MVCC)
在操作开始时,WiredTiger会向操作提供数据的point-in-time快照,快照显示了数据在内存中的一致性视图
从3.6版开始,MongoDB将WiredTiger配置为每隔60秒创建检查点(即将快照数据写入磁盘)
在早期版本中,MongoDB将检查点设置为在WiredTiger中每隔60秒或写入2 GB日志数据时(以先发生的为准)对用户数据进行检查

日志
WiredTiger将日志与检查点结合使用,以确保数据的持久性
WiredTiger日志将保留检查点之间的所有数据修改
如果MongoDB在两个检查点之间退出,它将使用日志重播自上一个检查点以来修改的所有数据

压缩
使用WiredTiger存储引擎,MongoDB会对所有集合和索引进行压缩,压缩以牺牲额外的CPU为代价,最大限度地减少了磁盘的使用
默认情况下,WiredTiger对所有集合使用block compression,并对索引使用prefix compression

内存使用
对于WiredTiger,MongoDB利用WiredTiger内部缓存和文件系统缓存
从MongoDB 3.4开始,默认WiredTiger内部缓存大小为以下两者中的较大值:
50% of (RAM - 1 GB)
256 MB
          

In-memory存储引擎

简介
从MongoDB 企业版3.2.6版开始,In-Memory存储引擎是64位版本中广泛使用(general availability GA)的一部分
除某些元数据和诊断数据外,In-Memory存储引擎不维护任何磁盘上的数据,包括配置数据,索引,用户凭据等

In-Memory存储引擎设置
配置--storageEngine选项值为inMemory;如果使用配置文件,则配置storage.engine
配置--dbpath,如果使用配置文件则配置storage.dbPath。尽管In-Memory存储引擎不会将数据写入文件系统,
但它会在--dbpath中维护小型元数据文件和诊断数据以及用于构建大型索引的临时文件
mongod --storageEngine inMemory --dbpath


并发
In-Memory存储引擎对于写入操作使用了document级并发控制
多个客户端可以同时修改集合的不同文档

内存使用
默认情况下,In-Memory存储引擎使用50%的物理RAM减去1GB
如果写操作的数据超过了指定的内存大小,则MongoDB返回错误:
"WT_CACHE_FULL: operation would overflow cache"
要指定新大小,可使用YAML格式配置文件的

事务
从MongoDB 4.2开始,复制集和分片集群上支持事务,其中:
主成员节点使用WiredTiger存储引擎,同时,辅助成员使用WiredTiger存储引擎或In-Memory存储引擎
在MongoDB 4.0中,只有使用WiredTiger存储引擎的复制集才支持事务
          

安装

yum安装

安装
进入/etc/yum.repos.d目录,创建文件mongodb-org-5.0.repo

cd /etc/yum.repos.d

vim mongodb-org-5.0.repo

[mongodb-org]
name=MongoDB Repository
baseurl=http://mirrors.aliyun.com/mongodb/yum/redhat/7Server/mongodb-org/5.0/x86_64/
gpgcheck=0
enabled=1


更新yum

yum update


安装

yum -y install mongodb-org


修改配置文件
查看mongo的安装位置

whereis mongod


修改配置文件

vim /etc/mongod.conf


bindIp: 172.0.0.1 改为 bindIp: 0.0.0.0

mongdb的使用
查看

systemctl status mongod.service


启动

systemctl start mongod.service


停止

systemctl stop mongod.service


重启
systemctl restart mongod.service查看

systemctl status mongod.service


设置开机自启动

systemctl enable mongod.service



mongo shelld的使用
启动

cd /usr/bin

./mongo



启动【指定主机和端口】

cd /usr/bin

./mongo--host=主机IP --port=端口


          

docker安装

安装
拉取镜像

docker pull mongo:4.4.14-focal


创建容器

docker run -itd --name mongo -p 8036:27017  mongo:4.4.14-focal --auth



配置管理员
进入容器

docker exec -it mongo bash


进入终端

mongo


进入admin数据库

use admin


创建管理员账户

db.createUser({ user: "root", pwd: "Jiakewei521", roles: [{ role: "root", db: "admin" }] })


验证用户添加是否成功

db.auth("root", "Jiakewei521");


如果返回1,则表示成功

进入终端
进入容器

docker exec -it mongo bash


进入终端

mongo


以管理员身份登录

use admin

switched to db admin
db.auth("root","Jiakewei521")

安全认证

MongoDB安全认证

简介
MongoDB 默认是没有账号的,可以直接连接,无须身份验证,但实际项目中肯定是要权限验证的,否则后果不堪设想

认证相关操作
docker以auth方式创建MongoDB容器

docker run -itd --name mongo5 -p 27017:27017 mongo:xxx --auth



备份数据

mongodump -h 127.0.0.1:27017 -d mydb -o /usr/local



恢复数据(在用户认证之后)

mongorestore -h localhost -u root -p 123456 --db mydb /dump/mydb --authenticationDatabase admin


        

基于角色的访问控制相关知识

用户命令
修改密码

db.changeUserPassword( '账号' , '密码' );


添加角色

db.grantRolesToUser('用户名',[{ role:'角色名', db:'数据库名'}])


删除用户

db.dropUser("用户名")


验证用户【返回 1 说明认证成功】

db.auth("账号","密码")



内置角色
root    超级账号,超级权限
read    允许用户读取指定数据库
readwrite    允许用户读写指定数据库
dbAdmin    可以读取任何数据库并对库进行清理、修改、压缩,获取统计信息、执行检查等操作
userAdmin    可以在指定数据库里创建、删除和管理用户
readAnyDatabase    可以读取任何数据库中的数据,除了数据库config和local之外
readwriteAnyDatabase    可以读写任何数据库中的数据,除了数据库config和local之外
userAdminAnyDatabase    可以在指定的数据库中创建和修改用户,除了数据库config和local之外
dbAdminAnyDatabase    可以读取任何数据库并对库进行清理、修改、压缩,获取统计信息、执行检查等操作,除了数据库config和local之外
backup    备份数据权限
restore    从备份中恢复数据的权限

mongdb中用户默认对应的角色
数据库用户    read、readwrite
数据库管理角色    dbAdmin、userAdmin
所有数据库角色    readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、 dbAdminAnyDatabase
备份恢复角色    backup、restore
超级用户角色    root
         

管理员

创建管理员
MongoDB 服务端开启安全检查之前,至少需要有一个管理员账号,admin 数据库中的用户都被视为管理员
如果 admin 库没有任何用户的话,即使在其他数据库中创建了用户,启用身份验证,
默认的连接方式依然会有超级权限,即仍然可以不验证账号密码照样能进行 CRUD,安全认证相当于无效
进入容器

docker exec -it mongo bash


进入终端

mongo


进入admin数据库

use admin


创建管理员账户

db.createUser({ user: "root", pwd: "Jiakewei521", roles: [{ role: "root", db: "admin" }] })


验证用户添加是否成功

db.auth("root", "Jiakewei521");


如果返回1,则表示成功

管理员登录
客户端管理员以root用户登录,安全认证通过后,拥有对所有数据库的所有权限
进入容器

docker exec -it mongo bash


进入终端

mongo


以管理员身份登录

use admin
switched to db admin
db.auth("root","Jiakewei521")


        

普通用户

创建普通用户
创建mydb数据库并创建两个用户,zhangsan 拥有读写权限,lisi 拥有只读权限测试这两个账户的权限。以超级管理员登录测试权限

> use mydb
switched to db mydb
>  db.c1.insert({name:"testdb1"})
WriteResult({ "nInserted" : 1 })
> db.c2.insert({name:"testdb1"})
WriteResult({ "nInserted" : 1 })
> show tables
c1
c2
> db.c1.find()
{ "_id" : ObjectId("62a00e5c1eb2c6ab85dd5eec"), "name" : "testdb1" }
> db.c1.find({})
{ "_id" : ObjectId("62a00e5c1eb2c6ab85dd5eec"), "name" : "testdb1" }
> show dbs
admin   0.000GB
config   0.000GB
local   0.000GB
mydb    0.001GB
>

普通用户登录
普通用户现在仍然像以前一样进行登录,如下所示直接登录进入 mydb数据库中,登录是成功的,只是登录后日志少了很多东西,
而且执行 show dbs 命令,以及 show tables 等命令都是失败的,即使没有被安全认证的数据库,用户同样操作不了,
这都是因为权限不足,一句话:用户只能在自己权限范围内的数据库中进行操作

> db.auth("zhangsan","123456")
1
> show dbs
mydb 0.001GB
> show tables
c1
c2        
        

常用命令

数据库命令

查看数据库

show dbs;



切换数据库 如果没有对应的数据库则创建

use 数据库名;



创建集合

db.createCollection("集合名")



查看集合

showtables;
show collections;



删除集合

db.集合名.drop();



删除当前数据库

db.dropDatabase();


        

添加文档

注意
添加单个文档,如果集合不存在,会创建一个集合
如果不指定id, MongoDB会使用ObjectId的value作为id

添加单个文档

db.inventory.insertOne(
{ item: "canvas", qty: 100, tags: ["cotton"], size: { h: 28, w: 35.5, uom: "cm" } })



添加多个文档

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" }}])    

更新文档

测试数据

db.inventory.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status: "A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" }, status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" }, status: "A" }] );



操作1
更新item值为“paper”的第一个文档 将它的size.uom设置为“cm”,status值设置为"P"
并且把lastModified字段更新为当前时间,如果该字段不存在,则生成一个

db.inventory.updateOne(
{ item: "paper" },
{$set: { "size.uom": "cm", status: "P" },
$currentDate: { lastModified: true }}
)



操作2
更新qty属性值小于50的文档 将它的size.uom设置为“in”,status值设置为"P"
并且把lastModified字段更新为当前时间,如果该字段不存在,则生成一个

把item属性为“paper”的文档替换成下面的内容

db.inventory.replaceOne(
{ item: "paper" },{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 40 } ] })

删除文档

删除集合所有文档

db.inventory.deleteMany({})



删除指定条件的文档

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



最多删除1个指定条件的文档

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

查询文档

测试数据

db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);



查询集合所有文档

db.inventory.find({})



查询指定内容的文档【size内容顺序要匹配】

db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )



匹配size中uom属性为“in”的文档

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



匹配size中h属性值小于15的文档

db.inventory.find( { "size.h": { $lt: 15 } } )



匹配h属性小于15并且uom属性为“in”,并且“status”属性为"D"的文档

db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )

聚合命令

聚合操作

聚合操作
通过聚合操作可以处理多个文档,并返回计算后的结果:对多个文档进行分组/对分组的文档执行操作并返回单个结果/分析数据变化

聚合管道
分别由多个阶段来处理文档,每个阶段的输出是下个阶段的输入,返回的是一组文档的处理结果
例如,total、average、maxmium、minimium

测试数据

db.orders.insertMany([
{ _id: 0, name: "Pepperoni", size: "small", price: 19,quantity: 10, date: ISODate( "2030-03-13T08:14:30Z" ) },
{ _id: 1, name: "Pepperoni", size: "medium", price: 20,quantity: 20, date : ISODate( "2030-03-13T09:13:24Z" ) },
{ _id: 2, name: "Pepperoni", size: "large", price: 21,quantity: 30, date : ISODate( "2030-03-17T09:22:12Z" ) },
{ _id: 3, name: "Cheese", size: "small", price: 12,quantity: 15, date : ISODate( "2030-03-13T11:21:39.736Z" ) },
{ _id: 4, name: "Cheese", size: "medium", price: 13,quantity:50, date : ISODate( "2031-01-12T21:23:13.331Z" ) },
{ _id: 5, name: "Cheese", size: "large", price: 14,quantity: 10, date : ISODate( "2031-01-12T05:08:13Z" ) },
{ _id: 6, name: "Vegan", size: "small", price: 17,quantity: 10, date : ISODate( "2030-01-13T05:08:13Z" ) },
{ _id: 7, name: "Vegan", size: "medium", price: 18,quantity: 10, date : ISODate( "2030-01-13T05:10:13Z" ) }
])



示例1
计算尺寸为medium的订单中,每种类型的订单数量

db.orders.aggregate( [
// Stage 1: 匹配size:"medium"的文档
{
$match: { size: "medium" }
},
// Stage 2: 根据name统计过滤后的文档,并把"quantity"值相加
{
$group: { _id: "$name", totalQuantity: { $sum: "$quantity" } }
}
] )



示例2
更复杂的例子

db.orders.aggregate( [
// Stage 1: 根据日期范围过滤
{
$match:
{
"date": { $gte: new ISODate( "2030-01-01" ), $lt: new ISODate( "2030-01-30" ) }
}
},
// Stage 2: 对过滤后文档以日期为条件进行分组并计算
{
$group:
{
_id: { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
totalOrderValue: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageOrderQuantity: { $avg: "$quantity" }
}
},
// Stage 3: 按照订单价值倒序排列文档
{
$sort: { totalOrderValue: -1 }
}
] )  


          

聚合管道顺序优化

聚合管道顺序优化
聚合管道在执行的过程中有一个优化的阶段,以提高性能

优化前

$addFields: {
maxTime: { $max: "$times" },
minTime: { $min: "$times" }
} },
{ $project: {
_id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
avgTime: { $avg: ["$maxTime", "$minTime"] }
} },
{ $match: {
name: "Joe Schmoe",
maxTime: { $lt: 20 },
minTime: { $gt: 5 },
avgTime: { $gt: 7 }
} }




优化后
优化思路:优化器把$match阶段分成了4个独立的过滤器,尽可能把过滤器放在$project操作前面,优化后的聚合管道如下

{ $match: { name: "Joe Schmoe" } },
{ $addFields: {
maxTime: { $max: "$times" },
minTime: { $min: "$times" }
} },
{ $match: { maxTime: { $lt: 20 }, minTime: { $gt: 5 } } },
{ $project: {
_id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
avgTime: { $avg: ["$maxTime", "$minTime"] }
} },
{ $match: { avgTime: { $gt: 7 } } }


            

索引命令

索引

简介
索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构
索引是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单

作用
相当于图书的目录,可以根据目录中的页码快速找到所需的内容
提高数据库的查询效率,没有索引的话,查询会进行全表扫描,数据量大时严重降低了查询效率
          

索引管理

获取索引

db.collection.getIndexes()



获取索引数量

db.collection.totalIndexSize()



重建索引

db.collection.reIndex()



删除索引
注意: _id 对应的索引是删除不了的

db.collection.dropIndex("INDEX-NAME")
db.collection.dropIndexes()            

单键索引

简介
MongoDB默认所有的集合在_id字段上有一个索引

创建索引
注意:1代表升序,-1代表降序
创建索引:db.test.createIndex( { key字段: 1 } )
创建索引【有内嵌字段】:db.test.createIndex( { "key字段.子key字段": 1 } )
创建复合索引:db.test.createIndex( { "key字段.子key字段": 1 ,"key字段.子key字段": 1...} )

创建复合

示例
示例数据

db.test.inseartOne({
"_id": 123,
"score": 356,
"location": { province: "Hebei", city: "Tangshan" }
})


创建索引

db.test.createIndex( { score: 1 } )


创建内嵌字段的索引

db.test.createIndex( { "location.province": 1 } )


创建复合索引

db.test.createIndex( {score: 1, "location.province": 1 } )

多键索引

简介
多键索引用于为数组中的元素创建索引

示例
测试数据

[{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] },
{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] },
{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] },
{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] },
{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }]



创建多键索引

db.inventory.createIndex( { ratings: 1 } )


原理解释:
MongoDB使用多键索引查找在“ratings”数组中有“5”的文档,
然后,MongoDB检索这些文档并筛选“ratings”数组等于查询数组“[5,9]”的文档

地理空间索引

地理空间索引
针对地理空间坐标数据创建索引。2dsphere索引用于存储和查找球面上的点,2d索引用于存储和查找平面上的点

db.company.insert(
{
loc : { type: "Point", coordinates: [ 116.502451, 40.014176 ] },
name: "军博地铁",
category : "Parks"
}
)


 

db.company.createIndex( { loc : "2dsphere" } )


 

db.company.find({
"loc" : {
"$geoWithin" : {
"$center":[[116.482451,39.914176],0.05]
}
}
})


 

db.places.insert({"name":"aa","addr":[32,32]})
db.places.insert({"name":"bb","addr":[30,22]})
db.places.insert({"name":"cc","addr":[28,21]})
db.places.insert({"name":"dd","addr":[34,26]})
db.places.insert({"name":"ee","addr":[34,27]})
db.places.insert({"name":"ff","addr":[39,28]})


 

db.places.find({})
db.places.createIndex({"addr":"2d"})
db.places.find({"addr":{"$within":{"$box":[[0,0],[30,30]]}}})

全文索引

全文索引
MongoDB提供了针对string内容的文本查询,Text Index支持任意属性值为string或string数组元素的索引查询
注意:一个集合仅支持最多一个Text Index,中文分词不理想推荐ES
 

db.fullText.insert({name:"aa",description:"no pains,no gains"})
db.fullText.insert({name:"ab",description:"pay pains,get gains"})
db.fullText.insert({name:"ac",description:"a friend in need,a friend in deed"})



创建索引并指定语言

db.fullText.createIndex(
{ description : "text" },
{ default_language: "english" }
)

db.fullText.find({"$text": {"$search": "pains"}})



全文索引名称

db.collection.createIndex(
{
content: "text",
"users.comments": "text",
"users.profiles": "text"
}
)


生成的默认索引名:content_text_users.comments_text_users.profiles_text

指定名称

db.collection.createIndex(
{
content: "text",
"users.comments": "text",
"users.profiles": "text"
},
{
name: "MyTextIndex"
}
)



使用指定名称删除索引

db.collection.dropIndex("MyTextIndex")


          

哈希索引

哈希索引
针对属性的哈希值进行索引查询,当要使用Hashed index时,MongoDB能够自动的计算hash值,
无需程序计算hash值。注:hash index仅支持等于查询,不支持范围查询
 

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


创建复合hash索引,4.4以后的版本

db.collection.createIndex( { "fieldA" : 1, "fieldB" : "hashed", "fieldC" : -1 } )

Java操作

搭建

搭建

依赖
      

    <!--mongodb--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>


          配置文件
       

   spring:data:mongodb:host: ipport: 端口username: 账号password: 密码database: 数据库authentication-database: admin


        

实体类注解

Document(collection="")
位置:实体类上
作用:声明mongdb集合名
注意:若未加 @Document ,则识别mongdb集合名为实体类名小写

Id
位置:属性上方
表明是主键,不可重复,自带索引

Field("名称")
位置:属性上方
作用:声明mongdb集合中的key名
注意:若未加 @Field("名称") ,则识别mongdb集合中的key名为实体类属性名

JsonFormat
作用:后端格式化日期后返回给前端
@JsonFormat(pattern = “yyyy-MM-dd”, timezone = “GMT+8”)
private Date birthday;//生日

@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”, timezone = “GMT+8”)
private Date createTime;//创建时间

@JsonFormat(pattern = DateUtils.LONG_TIME_FORMAT, timezone = “GMT+8”)
private Date modifyTime;//修改时间

Transient
作用:被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性。

Indexed
位置:属性上方/实体类上
作用:声明索引
唯一索引的话是@Indexed(unique = true)。
也可以对数组进行索引,如果被索引的列是数组时,MongoDB会索引这个数组中的每一个元素。
也可以对整个Document进行索引,排序是预定义的按插入BSON数据的先后升序排列

CompoundIndex
位置:实体类上
作用:声明复合索引
示例:
@CompoundIndex(name = 'age_idx', def = “{'lastName': 1, 'age': -1}”)
此索引名为age_idx,lastName和age将作为复合索引

实体类示例

banner

@Data
@Document("banner")
public class Banner {
@Id
private String _id;//mongdb的主键
private Integer bannerId;//自己定义一个主键,用于删改查,记得添加时要随机生成主键,保证唯一性
private String bannerName;//轮播图名称
private String bannerUrl;//地址
}            

Template

MongoTemplate

使用

@Autowired
private MongoTemplate mongoTemplate;

增加

增加单个数据

mongoTemplate.insert(banner);


insert: 若新增数据的主键已经存在,则会抛 org.springframework.dao.DuplicateKeyException 异常提示主键重复,不保存当前数据
 

mongoTemplate.save(banner);


save: 若新增数据的主键已经存在,则会对当前已经存在的数据进行修改操作。

修改

根据自定义id修改

public void update(Banner banner) {
//org.springframework.data.mongodb.core.query.Query/Criteria/Update
Query query = new Query();
Criteria criteria = new Criteria();
// 设置查询条件
criteria.and("bannerId").is(banner.getBannerId());
query.addCriteria(criteria);
//创建Update,修改字段 例如把title修改为params.getTitle()
Update update = new Update().set("bannerName", banner.getBannerName()).set("bannerUrl", banner.getBannerUrl());
//执行修改操作,返回修改成功的条数
mongoTemplate.updateMulti(query,update,Banner.class);
}

删除

根据主键删除

public void delete(String id) {
//org.springframework.data.mongodb.core.query.Query/Criteria
Query query = new Query();
Criteria criteria = new Criteria();
// 设置查询条件
criteria.and("_id").is(id);
query.addCriteria(criteria);
mongoTemplate.remove(query, Banner.class);
}




删除集合中全部数据

public void dropCollection(String collectionName) {
// 计算表中数据的条数并删除
// 查询表数据条数
Query query = new Query();
List
<NationalPostPlatformUserVO> all = mongoTemplate.findAll(NationalPostPlatformUserVO.class);long count = all.size();if (count > 0) {// 删除后,就留下表明。字段和值都删除mongoTemplate.remove(query, NationalPostPlatformUserVO.class);}}


          

基本查询

根据自定义id查找

public Banner findById(Integer id) {
//org.springframework.data.mongodb.core.query.Query/Criteria
Query query = new Query();
Criteria criteria = new Criteria();
// 设置查询条件
criteria.and("bannerId").is(id);
query.addCriteria(criteria);
return mongoTemplate.findOne(query, Banner.class);
}



查询全部

public List
<Banner> findAll() {return mongoTemplate.findAll(Banner.class);}查询总数long totals = mongoTemplate.count(new Query(), Banner.class);条件查询mongoTemplate.findOne 查询一条mongoTemplate.find查询多条Query query = new Query();Criteria criteria = new Criteria();criteria.and("bannerName").is(bannerName);//条件查询query.addCriteria(criteria);return mongoTemplate.findOne(query, Banner.class);

分页查询

分页封装类

@Data
public class PageResult {
protected List records;
protected long total;
protected long size;
protected long current;
}



分页查询

public PageResult search(int page, int size) {
// 查询总数
long totals = mongoTemplate.count(new Query(), Banner.class);
//查询全部数据
List
<Banner> banners = mongoTemplate.findAll(Banner.class);// 分页查询PageResult<Banner> bannerPage=new PageResult<>();bannerPage.setRecords(banners);bannerPage.setTotal(totals);bannerPage.setSize(size);bannerPage.setCurrent(page);return bannerPage;}

Criteria条件详解

详解
and()    $and    并且
andOperator()    $and    并且
orOperator()    $or    或者
gt()    $gt    大于
gte()    $gte    大于等于
in()    $in    是否被包含在数组或者list内
is()    $is    等于
regex()        $regex    正则表达式用于模式匹配,基本上是用于文档中的发现字符串  (下面有例子)
lt()    $lt    小于
lte()    $lte    小于等于
nin    $nin
不包含  
          

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/32004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【java实习评审】对推电影详情模块的基本电影模型设计到位,并能考虑到特色业务的设计

大家好&#xff0c;本篇文章分享一下【校招VIP】免费商业项目"推电影"第一期 电影详情模块 Java同学的开发文档周最佳作品。该同学来自暨南大学电子信息专业。 本项目的商业出发点&#xff1a; 豆瓣评分越来越水&#xff0c;不太符合年青人的需求&#xff0c;我们推…

【雕爷学编程】Arduino动手做(12)---霍尔磁场传感器模块2

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

【Hystrix技术指南】(5)Command创建和执行实现

创建流程 构建HystrixCommand或者HystrixObservableCommand对象 *使用Hystrix的第一步是创建一个HystrixCommand或者HystrixObservableCommand对象来表示你需要发给依赖服务的请求。 若只期望依赖服务每次返回单一的回应&#xff0c;按如下方式构造一个HystrixCommand即可&a…

淘宝商品价格查询接口 批量获取商品详情页数据 支持高并发(含调用实例)

接口开发背景 淘宝商品价格查询可以帮助消费者了解和比较不同商品的价格&#xff0c;从而能够作出更明智的购买决策。通过价格查询&#xff0c;消费者可以找到最具性价比的商品&#xff0c;避免被高价或低价的商品误导。此外&#xff0c;价格查询还可以帮助消费者了解市场行情…

shell脚本条件测试语句,if,case

shell脚本条件测试语句&#xff0c;if&#xff0c;case 一.条件测试1.1test命令1.2文件测试1.2.1文件测试常见选项 1.3数值比较1.4字符串比较1.5逻辑测试 二.if语句2.1单分支结构2.3多分支 三.case语句 一.条件测试 1.1test命令 测试特定的表达式是否成立&#xff0c;当条件成…

BGP基础实验建邻+宣告实验

实验题目如下&#xff1a; 实验拓扑如下&#xff1a; 实验要求如下&#xff1a; 【1】除R5的5.5.5.0环回外&#xff0c;其他所有的环回均可互相访问 实验思路如下&#xff1a; &#xff08;1&#xff09;合理的IP配置 &#xff08;2&#xff09;合理的BGP配置 &#xff08;…

SQL | 计算字段

7-创建计算字段 7.1-计算字段 存储在数据库中的数据一般不是我们所需要的字段格式&#xff0c; 需要公司名称&#xff0c;同时也需要公司地址&#xff0c;但是这两个数据存储在不同的列中。 省&#xff0c;市&#xff0c;县和邮政编码存储在不同的列中&#xff0c;但是当我们…

工厂老化设备维护的重要性及如何维护老化设备?

工业领域的老化设备问题日益凸显&#xff0c;对于保持生产稳定和效率至关重要。本文将探讨工厂老化设备维护的重要性&#xff0c;并介绍如何通过PreMaint设备数字化平台实现对老化设备的高效维护&#xff0c;从而确保工厂持续高效运转。 一、工厂老化设备的重要性 随着时间的推…

基于Python爬虫+词云图+情感分析对某东上完美日记的用户评论分析

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

在SPSS中实现数据转置

在使用SPSS开展数据分析的过程中&#xff0c;有时候不可避免需要对数据进行转置处理。 例如Kendall协同系数检验和组内相关系数&#xff08;ICC&#xff09;检验这两种方法都可以检验定量数据的一致性程度&#xff0c;但是这两种方法对数据的要求不同。 组内相关系数&#xf…

layui 集成 ztree异步加载

首先&#xff0c;layui环境搭建&#xff0c;ztree环境引入 ztree的js和css都要引入&#xff0c;我这里暂时用的是core包> 静态&#xff0c;一句话就够了 <!-- 左侧菜单树形组件 --><div class"layui-col-md3"><div class"layui-footer "…

Ajax-概念、Http协议、Ajax请求及其常见问题

Ajax Ajax概念Ajax优缺点HTTP协议请求报文响应报文 Ajax案例准备工作express基本使用创建一个服务器 发送AJAX请求GET请求POST请求JSON响应 Ajax请求出现的问题IE缓存问题Ajax请求超时与网络异常处理Ajax手动取消请求Ajax重复发送请求问题 Ajax概念 AJAX 全称为Asynchronous J…

干货 | 详述 Elasticsearch 向量检索发展史

1. 引言 向量检索已经成为现代搜索和推荐系统的核心组件。 通过将复杂的对象&#xff08;例如文本、图像或声音&#xff09;转换为数值向量&#xff0c;并在多维空间中进行相似性搜索&#xff0c;它能够实现高效的查询匹配和推荐。 图片来自&#xff1a;向量数据库技术鉴赏【上…

安科瑞物联网表在虚拟电厂的应用

安科瑞 崔丽洁 应用场景 一般应用于控制中心 功能 能计量当前组合有功电能&#xff0c;正向有功电能&#xff0c;反向有功电能&#xff0c;正向无功电能&#xff0c;反向无功电能&#xff1b; ADW300支持RS485通讯、LORA通讯、NB、4G及Wifi通讯&#xff1b; 三套时段表,一年可以…

[oeasy]python0081_[趣味拓展]ESC键进化历史_键盘演化过程_ANSI_控制序列_转义序列_CSI

光标位置 回忆上次内容 上次了解了 新的转义模式 \033 逃逸控制字符 escape 这个字符 让字符串 退出标准输出流进行控制信息的设置 可以设置 光标输出的位置 ASR33中的ALT MODE 是 今天的ESC键吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#x1f914; 查询文档…

关于APP备案、小程序备案的问题,如何备案?

近日&#xff0c;工信部发布了关于开展移动互联网应用程序备案工作的通知。为落实相关法律法规要求&#xff0c;促进互联网行业规范健康发展&#xff0c;进一步做好移动互联网信息服务管理&#xff0c;现组织开展移动互联网应用程序&#xff08;以下简称 APP&#xff09;备案工…

安灯Andon系统的应用与优势

安灯系统是一款与硬件相结合&#xff0c;实时了解机台与工位状态&#xff0c;让异常的信息得到快速、高效的解决的系统软件&#xff0c;同时记录每次异常报警的种类、响应时间和处理问题用时&#xff0c;提供改善生产管理和人员考核的数据参考&#xff0c;实现透明、快速的生产…

fetch-github-hosts间隔一年大更新v2.6发布,多端支持

前言 fetch-github-hosts是一款同步 github hosts 的工具&#xff0c;用于帮助您解决github时而无法访问的问题。在间隔了一年之久的时间&#xff0c;最近抽空将fetch-github-hosts的依赖及UI进行了一波大更新&#xff0c;同时也增加了一些实用的功能。 主要更新 更新了基础依…

Flutter:文件上传与下载(下载后预览)

Dio dio是一个强大的Dart Http请求库&#xff0c;提供了丰富的功能和易于使用的API&#xff0c;支持文件上传和下载。 这个就不介绍了&#xff0c;网上有很多的封装案例。 background_downloader 简介 适用于iOS&#xff0c;Android&#xff0c;MacOS&#xff0c;Windows和L…

Arcgis地图实战二:地图实时轨迹展示

1.最终效果预览 2.定时器执行方法 进入页面执行执行器 this.locationInterval setInterval(() > {this.getCurrentPosition();}, this.conf.LocateInterval);离开页面销毁 clearInterval(this.locationInterval);this.conf.LocateInterval为获取的数据同步中的定时器间隔…