当前位置: 首页 > news >正文

做的网站放在阿里云百度网络营销的概念

做的网站放在阿里云,百度网络营销的概念,电商行业的8种运营模式,门店管理系统软件排行文章目录 1、mongodb相关概念1.1、业务应用场景1.2、MongoDB简介1.3、体系结构1.3.1 数据库 (databases) 管理语法1.3.2 集合 (collection) 管理语法 1.4、数据模型1.5、MongoDB的特点 2、单机部署3、基本常用命令3.1、案例需求3.2、数据库操作3.2.1 选择和创建数据库3.2.2 数据… 文章目录 1、mongodb相关概念1.1、业务应用场景1.2、MongoDB简介1.3、体系结构1.3.1 数据库 (databases) 管理语法1.3.2 集合 (collection) 管理语法 1.4、数据模型1.5、MongoDB的特点 2、单机部署3、基本常用命令3.1、案例需求3.2、数据库操作3.2.1 选择和创建数据库3.2.2 数据库的删除 3.3、集合操作3.3.1 集合的显式创建3.3.2 集合的隐式创建常用3.3.3 集合的删除 3.4、文档基本CRUD3.4.1 文档的插入3.4.2 文档的基本查询3.4.3 文档的更新3.4.4 删除文档 3.5 文档的分页查询3.5.1 统计查询3.5.2 分页列表查询3.5.3 排序查询 3.6 文档的更多查询3.6.1 正则的复杂条件查询3.6.2 比较查询3.6.3 包含查询3.6.4 条件连接查询3.6.5 foreach查询 3.7 常用命令小结 4、文档间的对应关系4.1、一对一4.2、一对多/多对一4.3、多对多 5、索引-Index5.1、概述5.2、索引的类型5.2.1 单字段索引5.2.2 复合索引5.2.3 其他索引 5.3、索引的管理操作5.3.1 索引的查看5.3.2 索引的创建5.3.3 索引的移除 5.4、索引的使用5.4.1 执行计划5.4.2 涵盖的查询 6、SpringBoot整合MongoDB6.1、需求分析6.2、表结构分析6.3、技术选型6.3.1 mongodb-driver了解6.3.2 SpringDataMongoDB 6.4、文章微服务模块搭建6.5、文章评论实体类的编写6.6、文章评论的基本增删改查6.7、根据上级ID查询文章评论的分页列表6.8、MongoTemplate实现评论点赞 1、mongodb相关概念 官方文档 中文社区 官方中文文档 中文文档 1.1、业务应用场景 传统的关系型数据库如MySQL在数据操作的“三高”需求以及应对Web2.0的网站需求面前显得力不从心。 解释“三高”需求 High performance - 对数据库高并发读写的需求。Huge Storage - 对海量数据的高效率存储和访问的需求。High Scalability High Availability- 对数据库的高可扩展性和高可用性的需求。 而MongoDB可应对“三高”需求。 具体的应用场景如 1社交场景使用 MongoDB 存储存储用户信息以及用户发表的朋友圈信息通过地理位置索引实现附近的人、地点等功能。 2游戏场景使用 MongoDB 存储游戏用户信息用户的装备、积分等直接以内嵌文档的形式存储方便查询、高效率存储和访问。 3物流场景使用 MongoDB 存储订单信息订单状态在运送过程中会不断更新以 MongoDB 内嵌数组的形式来存储一次查询就能 将 订单所有的变更读取出来。 4物联网场景使用 MongoDB 存储所有接入的智能设备信息以及设备汇报的日志信息并对这些信息进行多维度的分析。 5视频直播使用 MongoDB 存储用户信息、点赞互动信息等。 这些应用场景中数据操作方面的共同特点是 数据量大写入操作频繁读写都很频繁价值较低的数据对事务性要求不高 对于这样的数据我们更适合使用MongoDB来实现数据的存储。 什么时候选择MongoDB 在架构选型上除了上述的三个特点外可以考虑以下的一些问题 应用不需要事务及复杂 join 支持新应用需求会变数据模型无法确定想快速迭代开发应用需要2000-3000以上的读写QPS更高也可以应用需要TB甚至 PB 级别数据存储应用发展迅速需要能快速水平扩展应用要求存储的数据不丢失应用需要99.999%高可用应用需要大量的地理位置查询、文本查询 如果上述有1个符合可以考虑 MongoDB2个及以上的符合选择 MongoDB 绝不会后悔。 思考如果用MySQL呢 答相对MySQL可以以更低的成本解决问题包括学习、开发、运维等成本 1.2、MongoDB简介 MongoDB是一个开源、高性能、无模式的文档型数据库当初的设计就是用于简化开发和方便扩展是NoSQL数据库产品中的一种。是最像关系型数据库MySQL的非关系型数据库。 它支持的数据结构非常松散是一种类似于 JSON 的 格式叫BSON所以它既可以存储比较复杂的数据类型又相当的灵活。 MongoDB中的记录是一个文档它是一个由字段和值对field:value组成的数据结构。MongoDB文档类似于JSON对象即一个文档认为就是一个对象。字段的数据类型是字符型它的值除了使用基本的一些类型外还可以包括其他文档、普通数组和文档数组。 1.3、体系结构 Mongo和Mysql对比 MongoDB 数据模型是面向文档的, 所谓文档就是一种类似于 JSON 的结构, 简单理解 MongoDB 这个数据库中存在的是各种各样的 JSONBSON 数据库 (database) 数据库是一个仓库, 存储集合 (collection) 集合 (collection) 类似于数组, 在集合中存放文档 文档 (document) 文档型数据库的最小单位, 通常情况, 我们存储和操作的内容都是文档 在 MongoDB 中, 数据库和集合都不需要手动创建, 当我们创建文档时, 如果文档所在的集合或者数据库不存在, 则会自动创建数据库或者集合隐式创建 1.3.1 数据库 (databases) 管理语法 操作语法查看所有数据库show dbs; 或 show databases;查看当前数据库db;切换到某数据库 (若数据库不存在则创建数据库)use db_name;删除当前数据库db.dropDatabase(); 1.3.2 集合 (collection) 管理语法 操作语法查看所有集合show collections;创建集合db.createCollection(collection_name);删除集合db.collection_name.drop() 1.4、数据模型 MongoDB的最小存储单位就是文档(document)对象。文档(document)对象对应于关系型数据库的行。 数据在MongoDB中以BSONBinary-JSON文档的格式存储在磁盘上。 BSONBinary Serialized Document Format是一种类json的一种二进制形式的存储格式简称Binary JSON。 BSON和JSON一样支持内嵌的文档对象和数组对象但是BSON有JSON没有的一些数据类型如Date和BinData类型。 BSON采用了类似于 C 语言结构体的名称、对表示方法支持内嵌的文档对象和数组对象具有轻量性、可遍历性、高效性的三个特点可以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高但它的缺点是空间利用率不是很理想。 Bson中除了基本的JSON类型string,integer,boolean,double,null,array和objectmongo还使用了特殊的数据类型。这些类型包括date,object id,binary data,regular expression 和code。每一个驱动都以特定语言的方式实现了这些类型查看你的驱动的文档来获取详细信息。 BSON数据类型参考列表 1.5、MongoDB的特点 MongoDB主要有如下特点 高性能 MongoDB提供高性能的数据持久性。特别是对嵌入式数据模型的支持减少了数据库系统上的I/O活动。 索引支持更快的查询并且可以包含来自嵌入式文档和数组的键。文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地理位置索引可用于构建各种 O2O 应用 mmapv1、wiredtiger、mongorocksrocksdb、in-memory 等多引擎支持满足各种场景需求。 Gridfs解决文件存储的需求。 高可用性 MongoDB的复制工具称为副本集replica set它可提供自动故障转移和数据冗余。 高扩展性 MongoDB提供了水平可扩展性作为其核心功能的一部分。 分片将数据分布在一组集群的机器上。海量数据存储服务能力水平扩展 从3.4开始MongoDB支持基于片键创建数据区域。在一个平衡的集群中MongoDB将一个区域所覆盖的读写只定向到该区域内的那些片。 丰富的查询支持 MongoDB支持丰富的查询语言支持读和写操作(CRUD)比如数据聚合、文本搜索和地理空间查询等。 其他特点如无模式动态模式、灵活的文档模型、 2、单机部署 笔者采用docker在服务器上部署MongoDB请看笔者的另一篇文章 Docker安装MongoDB_King Gigi.的博客-CSDN博客 3、基本常用命令 3.1、案例需求 存放文章评论的数据存放到MongoDB中数据结构参考如下 数据库articledb 3.2、数据库操作 3.2.1 选择和创建数据库 选择和创建数据库的语法格式 use 数据库名称查看有权限查看的所有的数据库命令 show dbs 或 show databases注意: 在 MongoDB 中集合只有在内容插入后才会创建 就是说创建集合(数据表)后要再插入一个文档(记录)集合才会真正创建。 查看当前正在使用的数据库命令 dbMongoDB 中默认的数据库为 test如果没有选择数据库集合将存放在 test 数据库中。 有一些数据库是保留的可以直接访问这些有特殊作用的数据库。 admin 从权限的角度来看这是root数据库。要是将一个用户添加到这个数据库这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行比如列出所有的数据库或者关闭服务器。local: 这个数据永远不会被复制可以用来存储限于本地单台服务器的任意集合。config: 当Mongo用于分片设置时config数据库在内部使用用于保存分片的相关信息。 当我们创建了一个数据库后再进行查看会发现我们创建的数据库并没有显示出来这是由于MongoDD的存储机制决定的 当使用 use articledb 的时候. articledb 其实存放在内存之中, 当 articledb 中存在一个 collection 之后, mongo 才会将这个数据库持久化到硬盘之中. show dbs admin 0.000GB config 0.000GB local 0.000GBuse articledb switched to db articledbshow dbs admin 0.000GB config 0.000GB local 0.000GBdb.articledb.insertOne({a: 3}) {acknowledged : true,insertedId : ObjectId(62e128b6a70e7344a5139207) }show dbs admin 0.000GB articledb 0.000GB config 0.000GB local 0.000GB3.2.2 数据库的删除 MongoDB 删除数据库的语法格式如下 db.dropDatabase()#提示主要用来删除已经持久化的数据库3.3、集合操作 集合类似关系型数据库中的表。 可以显示的创建也可以隐式的创建。 3.3.1 集合的显式创建 基本语法格式 db.createCollection(name)# name: 要创建的集合名称例如创建一个名为mycollection 的普通集合。 db.createCollection(mycollection)查看当前集合库中的文档表 show tables 或 show collections3.3.2 集合的隐式创建常用 当向一个集合中插入一个文档的时候如果集合不存在则会自动创建集合。 3.3.3 集合的删除 集合删除语法格式如下 db.集合.drop()#如果成功删除选定集合则 drop() 方法返回 true否则返回 false。例如要删除mycollection集合 db.mycollection.drop()3.4、文档基本CRUD 文档document的数据结构和 JSON 基本一样。 所有存储在集合中的数据都是 BSON 格式。 官方文档 3.4.1 文档的插入 单个文档插入 使用insert()方法向集合中插入文档语法如下 db.collection.insert(document or array of documents,{writeConcern: document,ordered: boolean} )参数 document要写入的文档。writeConcern写入策略默认为 1即要求确认写操作0 是不要求。ordered指定是否按顺序写入默认 true按顺序写入 示例 要向comment的集合(表)中插入一条测试数据 db.comment.insert({articleid:100000,content:今天天气真好阳光明媚,userid:1001,nickname:Rose,createdatetime:new Date(),likenum:NumberInt(10),state:null})提示 comment集合如果不存在则会隐式创建 mongo中的数字默认情况下是double类型如果要存整型必须使用函数NumberInt(整型数字)否则取出来就有问题了。 插入当前日期使用new Date() 插入的数据没有指定_id 会自动生成主键值 如果某字段没值可以赋值为null或不写该字段。 注意 1. 文档中的键/值对是有序的。 2. 文档中的值不仅可以是在双引号里面的字符串还可以是其他几种数据类型甚至可以是整个嵌入的文档)。 3. MongoDB区分类型和大小写。 4. MongoDB的文档不能有重复的键。 5. 文档的键是字符串。除了少数例外情况键可以使用任意UTF-8字符。 批量插入 语法 db.collection.insertMany([ document 1 , document 2, ... ],{writeConcern: document,ordered: boolean} )示例批量插入多条文章评论 // 插入多条记录db.comment.insertMany([ {_id:1,articleid:100001,content:我们不应该把清晨浪费在手机上健康很重要一杯温水幸福你我他。,userid:1002,nickname:相忘于江湖,createdatetime:new Date(2019-08-05T22:08:15.522Z),likenum:NumberInt(1000),state:1}, {_id:2,articleid:100001,content:我夏天空腹喝凉开水冬天喝温开水,userid:1005,nickname:伊人憔悴,createdatetime:new Date(2019-08-05T23:58:51.485Z),likenum:NumberInt(888),state:1}, {_id:3,articleid:100001,content:我一直喝凉开水冬天夏天都喝。,userid:1004,nickname:杰克船长,createdatetime:new Date(2019-08-06T01:05:06.321Z),likenum:NumberInt(666),state:1}, {_id:4,articleid:100001,content:专家说不能空腹吃饭影响健康。,userid:1003,nickname:凯撒,createdatetime:new Date(2019-08-06T08:18:35.288Z),likenum:NumberInt(2000),state:1}, {_id:5,articleid:100001,content:研究表明刚烧开的水千万不能喝因为烫嘴。,userid:1003,nickname:凯撒,createdatetime:new Date(2019-08-06T11:01:02.521Z),likenum:NumberInt(3000),state:1} ]);提示 插入时指定了_id 则主键就是该值。 如果某条数据插入失败将会终止插入但已经插入成功的数据不会回滚掉。 因为批量插入由于数据较多容易出现失败因此可以使用try catch进行异常捕捉处理测试的时候可以不处理。 try { // 插入多条记录 db.comment.insertMany([ {_id:1,articleid:100001,content:我们不应该把清晨浪费在手机上健康很重要一杯温水幸福你我他。,userid:1002,nickname:相忘于江湖,createdatetime:new Date(2019-08-05T22:08:15.522Z),likenum:NumberInt(1000),state:1}, {_id:2,articleid:100001,content:我夏天空腹喝凉开水冬天喝温开水,userid:1005,nickname:伊人憔悴,createdatetime:new Date(2019-08-05T23:58:51.485Z),likenum:NumberInt(888),state:1}, {_id:3,articleid:100001,content:我一直喝凉开水冬天夏天都喝。,userid:1004,nickname:杰克船长,createdatetime:new Date(2019-08-06T01:05:06.321Z),likenum:NumberInt(666),state:1}, {_id:4,articleid:100001,content:专家说不能空腹吃饭影响健康。,userid:1003,nickname:凯撒,createdatetime:new Date(2019-08-06T08:18:35.288Z),likenum:NumberInt(2000),state:1}, {_id:5,articleid:100001,content:研究表明刚烧开的水千万不能喝因为烫嘴。,userid:1003,nickname:凯撒,createdatetime:new Date(2019-08-06T11:01:02.521Z),likenum:NumberInt(3000),state:1} ]);} catch (e) {print (e); }3.4.2 文档的基本查询 查询数据的语法格式如下 db.collection_name.find(query, [projection])参数 查询所有 如果我们要查询comment集合的所有文档我们输入以下命令 db.comment.find() 或 db.comment.find({})这里我们会发现每条文档会有一个叫_id的字段这个相当于我们原来关系数据库中表的主键当在插入文档记录时没有指定该字段MongoDB会自动创建其类型是ObjectID类型。 如果我们在插入文档记录时指定该字段也可以其类型可以是ObjectID类型也可以是MongoDB支持的任意类型。 如果我想按一定条件来查询比如我想查询userid为1003的记录怎么办很简单只 要在find()中添加参数即可参数也是json格式如下 db.comment.find({userid:1003})如果只需要返回符合条件的第一条数据我们可以使用findOne命令来实现语法和find一样。 如查询用户编号是1003的记录但只最多返回符合条件的第一条记录 db.comment.findOne({userid:1003})投影查询Projection Query 如果要查询结果返回部分字段则需要使用投影查询不显示所有字段只显示指定的字段。 如查询结果只显示_id、userid、nickname : db.comment.find({userid:1003},{userid:1,nickname:1})默认_id 会显示。 如查询结果只显示、userid、nickname 不显示_id db.comment.find({userid:1003},{userid:1,nickname:1,_id:0})再例如查询所有数据但只显示_id、userid、nickname : db.comment.find({},{userid:1,nickname:1})3.4.3 文档的更新 更新文档的语法 db.collection.update(query, update, options) //或 db.collection.update(query,update,{upsert: boolean,multi: boolean,writeConcern: document,collation: document,arrayFilters: [ filterdocument1, ... ],hint: document|string // Available starting in MongoDB 4.2} )参数 ParameterTypeDescriptionquerydocument更新的选择条件updatedocument/pipeline要应用的修改upsertboolean可选。如果设置为true则在没有与查询条件匹配的文档时创建新的文档。默认值伟false如果找不到匹配项就不会插入新文档multiboolean可选。如果设置为true则更新符合查询条件的多个文档。如果设置为false则更新一个文档默认值为false 其他参数了解即可 单条记录的修改 如果我们想修改_id为1的记录点赞量为1001输入以下语句 db.comment.update({_id:1},{likenum:NumberInt(1001)})执行后我们会发现update方法已被弃用也可以用可以理解为Java中的比如说暂停线程的方法stop()虽然说被弃用但是依然能用我们要是想更新一条记录应该使用updateOne并且需要使用原子操作符来实现 为了解决这个问题我们需要使用修改器$set来实现命令如下 我们想修改_id为1的记录浏览量为889输入以下语句 db.comment.updateOne({_id:1},{$set:{likenum:NumberInt(889)}})这样就OK啦。 批量的修改 更新所有用户为1003 的用户的昵称为凯撒大帝。 //默认只修改第一条数据 db.comment.update({userid:1003},{$set:{nickname:凯撒2}}) //修改所有符合条件的数据 db.comment.update({userid:1003},{$set:{nickname:凯撒大帝2}},{multi:true})当然我们也可以使用updateMany()方法来操作 列值增长的修改 如果我们想实现对某列值在原有值的基础上进行增加或减少可以使用$inc 运算符来实现。 需求对3号数据的点赞数每次递增1 db.comment.update({_id:3},{$inc:{likenum:NumberInt(1)}})3.4.4 删除文档 删除文档的语法结构 db.集合名称.remove(条件) db.集合名称.remove(条件)以下语句可以将数据全部删除请慎用 db.comment.remove({})如果要删除comment集合中_id1的记录输入以下语句 db.comment.remove({_id:1})可以看到执行成功同样的remove()方法已被弃用 3.5 文档的分页查询 3.5.1 统计查询 统计查询使用count()方法语法如下 db.collection.count(query, options)参数 ParameterTypeDescriptionquerydocument查询选择条件optionsdocument可选。用于修改计数的额外选项。 统计所有记录数 统计comment集合的所有的记录数 db.comment.count()mongo_test db.comment.count() DeprecationWarning: Collection.count() is deprecated. Use countDocuments or estimatedDocumentCount. 5 mongo_test db.comment.countDocuments() 5 mongo_test db.comment.estimatedDocumentCount() 5按条件统计记录数 统计userid为1003的记录条数 db.comment.count({userid:1003})#默认情况下count() 方法返回符合条件的全部记录条数。3.5.2 分页列表查询 可以使用limit()方法来读取指定数量的数据使用skip()方法来跳过指定数量的数据。 基本语法如下所示 db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)如果你想返回指定条数的记录可以在find方法后调用limit来返回结果(TopN)默认值20例如 db.comment.find().limit(3)skip方法同样接受一个数字参数作为跳过的记录条数。前N个不要,默认值是0 db.comment.find().skip(3)分页查询需求每页2个第二页开始跳过前两条数据接着值显示3和4条数据 //第一页 db.comment.find().skip(0).limit(2) //第二页 db.comment.find().skip(2).limit(2) //第三页 db.comment.find().skip(4).limit(2)3.5.3 排序查询 sort() 方法对数据进行排序sort() 方法可以通过参数指定排序的字段并使用 1 和 -1 来指定排序的方式。 其中 1 为升序排列而 -1 是用于降序排列。 语法如下 db.COLLECTION_NAME.find().sort({KEY:1}) 或 db.集合名称.find().sort(排序方式)例如 对userid降序排列并对访问量进行升序排列 db.comment.find().sort({userid:-1,likenum:1})mongo_test db.comment.find().sort({userid:-1,likenum:1}) [{_id: 2,articleid: 100001,content: 我夏天空腹喝凉开水冬天喝温开水,userid: 1005,nickname: 伊人憔悴,createdatetime: ISODate(2019-08-05T23:58:51.485Z),likenum: 888,state: 1},{_id: 3,articleid: 100001,content: 我一直喝凉开水冬天夏天都喝。,userid: 1004,nickname: 杰克船长,createdatetime: ISODate(2019-08-06T01:05:06.321Z),likenum: 667,state: 1},{_id: 4,articleid: 100001,content: 专家说不能空腹吃饭影响健康。,userid: 1003,nickname: 凯撒大帝2,createdatetime: ISODate(2019-08-06T08:18:35.288Z),likenum: 2000,state: 1},{_id: 5,articleid: 100001,content: 研究表明刚烧开的水千万不能喝因为烫嘴。,userid: 1003,nickname: 凯撒大帝2,createdatetime: ISODate(2019-08-06T11:01:02.521Z),likenum: 3000,state: 1},{_id: ObjectId(6518ce02932a33a70a1134fd),articleid: 100000,content: 今天天气真好阳光明媚,userid: 1001,nickname: Rose,createdatetime: ISODate(2023-10-01T01:40:18.159Z),likenum: 10,state: null} ] mongo_test 提示 skip(), limilt(), sort()三个放在一起执行的时候执行的顺序是先 sort(), 然后是 skip()最后是显示的 limit()和命令编写顺序无关。 3.6 文档的更多查询 3.6.1 正则的复杂条件查询 MongoDB的模糊查询是通过正则表达式的方式实现的。格式为 db.collection.find({field:/正则表达式/}) 或 db.集合.find({字段:/正则表达式/})提示正则表达式是js的语法直接量的写法。 例如我要查询评论内容包含“开水”的所有文档代码如下 db.comment.find({content:/开水/})如果要查询评论的内容中以“专家”开头的代码如下 db.comment.find({content:/^专家/})3.6.2 比较查询 , , , 这个操作符也是很常用的格式如下: db.集合名称.find({ field : { $gt: value }}) // 大于: field value db.集合名称.find({ field : { $lt: value }}) // 小于: field value db.集合名称.find({ field : { $gte: value }}) // 大于等于: field value db.集合名称.find({ field : { $lte: value }}) // 小于等于: field value db.集合名称.find({ field : { $ne: value }}) // 不等于: field ! value示例查询评论点赞数量大于700的记录 db.comment.find({likenum:{$gt:NumberInt(700)}})3.6.3 包含查询 包含使用$in操作符。 示例查询评论的集合中userid字段包含1003或1004的文档 db.comment.find({userid:{$in:[1003,1004]}})不包含使用$nin操作符。 示例查询评论集合中userid字段不包含1003和1004的文档 db.comment.find({userid:{$nin:[1003,1004]}})3.6.4 条件连接查询 我们如果需要查询同时满足两个以上条件需要使用$and操作符将条件进行关联。相 当于SQL的and 格式为 $and:[ { },{ },{ } ]示例查询评论集合中likenum大于等于700 并且小于2000的文档 db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})如果两个以上条件之间是或者的关系我们使用 $or操作符进行关联 格式为 $or:[ { },{ },{ } ]示例查询评论集合中userid为1003或者点赞数小于1000的文档记录 db.comment.find({$or:[ {userid:1003} ,{likenum:{$lt:1000} }]})3.6.5 foreach查询 我们知道这些查询语句其实就是js的语法格式所有在查询得到结果后我们也可以通过forEach函数对结果进行遍历 db.posts.find().forEach(fucntion(doc) { print(Blog Post: doc.title) }) // 也可以通过箭头函数简化一下 db.comment.find().forEach((it) { print(it._id) });3.7 常用命令小结 选择切换数据库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}]})4、文档间的对应关系 一对一 (One To One)一对多/多对一(one to many / many to one)多对多 (Many To Many) 4.1、一对一 在MongoDB中可以通过内嵌文档的形式体现出一对一的关系比如夫妻 {name:黄蓉,husband:{name:郭靖} }一个文档对象一旦被嵌入到另一个文档对象中就绝不可能再被嵌入到其他文档对象中因此可以体现出一对一的关系 4.2、一对多/多对一 一对多的关系在实际开发中是非常常用的也是现实世界中出现频率比较高的关系 有两种方式可以体现一对多(或多对一)的关系以客户和订单为例 一关系在一的一方维护直接通过内嵌数组在数组中存放整个对象的方式这种方式不好因为如果对应的对象比较多的话文档就会看起来很复杂不易查询 {cust_id:ObjectId(5d272c817f2dc9e6986d82fb),cust_name:黑宋江,orders:[{_id: ObjectId(5d2614c42b1a4fdfd82bfda3),type:牛肉,count:2},{_id:ObjectId(5d272c817f2dc9e6986d82fa),type:酒,count:6}] }二一对多用户constom/订单orders 举个例子, 比如“用户-订单”这个一对多的关系中, 我们想查询某一个用户的所有或者某个订单, 我们可以在用户中添加订单的主键 先创建用户集合 db.constom.insert([{username:孙悟空},{username:猪八戒} ])再创建订单集合(添加一个userid属性该订单是谁的就给userid属性添加谁的_id) db.orders.insert({list:[辣椒,花椒,油],userid:ObjectId(5ebcfe39bc5756d0fed31ff3)//这个是孙悟空的_id代表该订单就是孙悟空的。 })通过userid再去查找每个人对应的订单 var userid db.constom.findOne({username:孙悟空})._id; db.orders.find({userid:userid})4.3、多对多 在关系型数据库中我们处理多对多关系的时候采用的方法一般是将两张表的主键抽取出来放到一张单独的关系表中将两张表的主键作为这张关系表的外键每次做关联查询的时候都要先到这张关系表中找出对应表的主键 在MongoDB中多对多采用的其实是类似与一对多的情况也是通过增加一些冗余的字段来记录关系 举个例子我们在关系型数据库中一般会以学生和老师作为例子这里同样我们也举这个 //多对多 // 先插入一些老师的信息 db.teachers.insertMany([{name:洪七公},{name:黄药师},{name:龟仙人} ]); db.teachers.find(); // 插入一些学生的信息并且将老师的id进行记录 db.students.insertMany([{name:郭靖,teachers_ids:[ObjectId(5d7f018b162f56aeed8aedda),ObjectId(5d7f018b162f56aeed8aeddb),ObjectId(5d7f018b162f56aeed8aeddc)]},{name:黄蓉,teachers_ids:[ObjectId(5d7f018b162f56aeed8aedda),ObjectId(5d7f018b162f56aeed8aeddb),ObjectId(5d7f018b162f56aeed8aeddc)]} ]); db.students.find();5、索引-Index 5.1、概述 索引支持在 MongoDB 中高效地执行查询如果没有索引MongoDB 必须执行全集合扫描即扫描集合中的每个文档以选择与查询语句 匹配的文档。 这种扫描全集合的查询效率是非常低的, 特别在处理大量的数据时, 查询可以要花费几十秒甚至几分钟, 这对网站的性能是非常致命的。 如果查询存在适当的索引, MongoDB 可以使用该索引限制必须检查的文档数。 索引是特殊的数据结构, 它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值按字段值排序。 索引项的排序支持有效的相等匹配和基于范围的查询操作。此外, MongoDB 还可以使用索引中的排序返回排序结果. MongoDB 和MySQL 一样使用的都是是 B Tree。 在之前的版本中Mongo使用的是B树但是现在都是使用B树了 Mongo官方文档为什么Mongo选择过B树 索引常用命令 // create index db.collection_name.createIndex({ userid : 1, username : -1 })// retrieve indexes db.collection_name.getIndexes()// remove indexes db.collection_name.dropIndex(index)// there are 2 ways to remove indexes: // 1. removed based on the index name // 2. removed based on the fieldsdb.collection_name.dropIndex( userid_1_username_-1 ) db.collection_name.dropIndex({ userid : 1, username : -1 })// remove all the indexes, will only remove non_id indexes db.collection_name.dropIndexes() 5.2、索引的类型 5.2.1 单字段索引 MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引称为单字段索引Single Field Index。 对于单个字段索引和排序操作索引键的排序顺序即升序或降序并不重要因为MongoDB可以在任何方向上遍历索引。 5.2.2 复合索引 MongoDB 还支持多个字段的用户定义索引, 即复合索引 Compound Index这个其实非常类似MySQL中的联合索引因为底层都是B树所有联合索引可能也有最左原则这种东西 复合索引中列出的字段顺序具有重要意义.例如, 如果复合索引由 { userid: 1, score: -1 } 组成, 则索引首先按 userid 正序排序, 然后 在每个 userid 的值内, 再在按 score 倒序排序. 5.2.3 其他索引 地理空间索引 Geospatial Index 文本索引 Text Indexes 哈希索引 Hashed Indexes 地理空间索引Geospatial Index 为了支持对地理空间坐标数据的有效查询, MongoDB 提供了两种特殊的索引: 返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引. 文本索引Text Indexes MongoDB 提供了一种文本索引类型, 支持在集合中搜索字符串内容.这些文本索引不存储特定于语言的停止词例如 “the”, “a”, “or”, 而将集合中的词作为词干, 只存储根词. 哈希索引Hashed Indexes 为了支持基于散列的分片, MongoDB 提供了散列索引类型, 它对字段值的散列进行索引.这些索引在其范围内的值分布更加随机, 但只支持相等匹配, 不支持基于范围的查询. 5.3、索引的管理操作 5.3.1 索引的查看 说明 返回一个集合中的所有索引的数组。 语法 db.collection_name.getIndexes()【示例】 查看comment集合中所有的索引情况 db.comment.getIndexes() [{v : 2,key : {_id : 1},name : _id_,ns : articledb.comment} ]结果中显示的是默认 _id 索引。 默认 _id 索引 MongoDB 在创建集合的过程中, 在 _id 字段上创建一个唯一的索引, 默认名字为 _id , 该索引可防止客户端插入两个具有相同值的文 档, 不能在 _id 字段上删除此索引. 注意该索引是唯一索引, 因此值不能重复, 即 _id 值不能重复的. 在分片集群中, 通常使用_id作为片键. 5.3.2 索引的创建 说明 在集合上创建索引。 语法 db.collection.createIndex(keys, options)参数 options更多选项列表 注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex() , 之后的版本使用了 db.collection.createIndex() 方法, ensureIndex() 还能用, 但只是 createIndex() 的别名. 举个 {userid:1} 表示由userid按照升序创建索引 {userid:1,nickname:-1}表示先按userid升序如果userid相等再按照nickname降序创建索引这里和MySQL一摸一样 【示例】 1单字段索引示例对userid 字段建立索引 db.comment.createIndex({userid:1}) {createdCollectionAutomatically : false,numIndexesBefore : 1,numIndexesAfter : 2,ok : 1 }参数1按升序创建索引 可以查看一下 db.comment.getIndexes() [{v : 2,key : {_id : 1},name : _id_,ns : articledb.comment},{v : 2,key : {userid : 1},name : userid_1,ns : articledb.comment} ]2复合索引对userid 和nickname 同时建立复合Compound索引 db.comment.createIndex({userid:1,nickname:-1}) {createdCollectionAutomatically : false,numIndexesBefore : 2,numIndexesAfter : 3,ok : 1 }查看一下索引 db.comment.getIndexes() [{v : 2,key : {_id : 1},name : _id_,ns : articledb.comment},{v : 2,key : {userid : 1},name : userid_1,ns : articledb.comment},{v : 2,key : {userid : 1,nickname : -1},name : userid_1_nickname_-1,ns : articledb.comment} ]5.3.3 索引的移除 说明可以移除指定的索引或移除所有索引 语法 # 删除某一个索引 $ db.collection.dropIndex(index)# 删除全部索引 $ db.collection.dropIndexes()其中index类型为string or document表示指定要删除的索引。可以通过索引名称或索引规范文档指定索引。若要删除文本索引请指定索引名称。 提示: _id 的字段的索引是无法删除的, 只能删除非 _id 字段的索引 示例 删除comment 集合中userid 字段上的升序索引 db.comment.dropIndex({userid:1}) { nIndexesWas : 3, ok : 1 }5.4、索引的使用 5.4.1 执行计划 分析查询性能Analyze Query Performance通常使用执行计划解释计划、Explain Plan来查看查询的情况如查询耗费的时间、是否基于索引查询等。同MySql的执行计划根据字段分析是否命中索引 那么通常我们想知道建立的索引是否有效效果如何都需要通过执行计划查看。 语法 $ db.collection_name.find( query, options ).explain(options)比如: 查看根据 user_id 查询数据的情况 未添加索引之前 stage : COLLSCAN, 表示全集合扫描 db.comment.find({userid:1003}).explain() {queryPlanner : {plannerVersion : 1,namespace : articledb.comment,indexFilterSet : false,parsedQuery : {userid : {$eq : 1003}},winningPlan : {stage : COLLSCAN, //表示全表扫描filter : {userid : {$eq : 1003}},direction : forward},rejectedPlans : [ ]},serverInfo : {host : 9ef3740277ad,port : 27017,version : 4.0.10,gitVersion : c389e7f69f637f7a1ac3cc9fae843b635f20b766},ok : 1 }下面对userid建立索引 db.comment.createIndex({userid:1}) {createdCollectionAutomatically : false,numIndexesBefore : 1,numIndexesAfter : 2,ok : 1 }再次查看执行计划 关键点看 “stage” : “IXSCAN” ,基于索引的扫描 5.4.2 涵盖的查询 这里如果直接看的话其实还是满难理解的但是如果我们结合MySQL来看就会发现这不就是MySQL里面的覆盖索引吗覆盖索引不就是减少了回表操作吗这样的话其实一下就能理解下面的介绍看来知识都是相通的还是应该多学底层应用层的东西会变但是底层的东西大部分都不会改变你看AVL树、红黑树这些数据结构都是上个世纪中期产生的现在用的还是这一套 当查询条件和查询的投影仅包含索引字段时 MongoDB 直接从索引返回结果, 而不扫描任何文档或将文档带入内存, 这些覆盖的查询十分有效 例如我们查询下面的索引执行计划 6、SpringBoot整合MongoDB 6.1、需求分析 这里会结合一个具体的业务场景小案例对用户评论进行CRUD 需要实现以下功能 基本增删改查API根据文章id查询评论评论点赞 6.2、表结构分析 数据库articledb集合就用我们上面一直在使用的comment 6.3、技术选型 6.3.1 mongodb-driver了解 mongodb-driver是mongo官方推出的java连接mongoDB的驱动包相当于JDBC驱动。我们通过一个入门的案例来了解mongodb-driver 的基本使用。 官方驱动说明和下载官方驱动示例文档 6.3.2 SpringDataMongoDB SpringData家族成员之一用于操作MongoDB的持久层框架封装了底层的mongodb-driver。 官网主页 6.4、文章微服务模块搭建 1搭建项目工程articlepom.xml引入依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.2/version relativePath/ !-- lookup parent from repository -- /parent groupIdcom.king/groupId artifactIdarticle/artifactId version0.0.1-SNAPSHOT/version namearticle/name descriptionDemo project for Spring Boot/description properties java.version1.8/java.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-mongodb/artifactId /dependency dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration excludes exclude groupIdorg.projectlombok/groupId artifactIdlombok/artifactId /exclude /excludes /configuration /plugin /plugins /build /project 2创建application.yml spring: #数据源配置 data: mongodb: # 主机地址 host: localhost # 数据库 database: articledb # 默认端口是27017 port: 27017 # 也可以使用uri连接 #uri: mongodb://192.168.40.134:27017/articledb 3创建启动类 com.king.article.ArticleApplication package com.king.article; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication public class ArticleApplication { public static void main(String[] args) { SpringApplication.run(ArticleApplication.class, args); } }我们启动一下空项目看Mongo连接是否正常一般就可以正常连接了 6.5、文章评论实体类的编写 创建实体类 创建包com.king.article包下建包po用于存放实体类创建实体类 这里有一点需要注意因为Mongo是可以进行横向拓展的所以可能会出现一个集合对应多个实体类的情况 package com.king.article.po; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; import java.io.Serializable; import java.time.LocalDateTime; import java.util.Date; /** * p * 文档评论实体类br/ * 把一个Java类生命为mongodb的文档可以通过collection参数指定这个类对应的文档 * /p * * since 2023-09-28 22:53 * author king**/ Data // 若未添加Document注解则该bean save到mongo的comment collection Document(collection comment)//指定对应的集合如果省略则默认为类名小写进行集合映射 CompoundIndex(def {userid: 1, nickname : -1}) // 添加复合索引先按userid排再按nickname降序排 public class Comment implements Serializable { private static final long serialVersionUID 21218312631312334L; // 主键标识该属性的值会自动对应mongodb的主键字段_id, 如果该属性名叫做 id, 则该注解可以省略否者必须写 Id private String id;//主键 private String content;//吐槽内容 private Date publishtime;//发布日期 // 添加了一个单子段的索引 Indexed private String userid;//发布人的ID private String nickname;//用户昵称 private LocalDateTime createdatetime;//评论的日期时间 private Integer likenum;//点赞数 private Integer replaynum;//回复数 private String state;//状态 private String parentid;//上级ID private String articleid;//文章id }说明 索引可以大大提升查询效率一般在查询字段上添加索引索引的添加可以通过Mongo的命令来添加也可以在Java的实体类中通过注解添加。 1单字段索引注解Indexed org.springframework.data.mongodb.core.index.Indexed.class 声明该字段需要索引建索引可以大大的提高查询效率。 Mongo命令参考 db.comment.createIndex({userid:1})2复合索引注解CompoundIndex org.springframework.data.mongodb.core.index.CompoundIndex.class 复合索引的声明建复合索引可以有效地提高多字段的查询效率。 Mongo命令参考 db.comment.createIndex({userid:1,nickname:-1})6.6、文章评论的基本增删改查 1创建数据访问接口 cn.itcast.article包下创建dao包包下创建接口 com.king.article.dao.CommentRepository package com.king.article.dao; import com.king.article.po.Comment; import org.springframework.data.mongodb.repository.MongoRepository; /** * p * * /p * * author king * since 2023-09-28 22:56 **/public interface CommentRepository extends MongoRepositoryComment, String { }2创建业务逻辑类com.king.article包下创建service包包下创建类 com.king.article.service.CommentService package com.king.article.service; import com.king.article.dao.CommentRepository; import com.king.article.po.Comment; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * p * 评论service方法 * /p * * since 2023-09-28 23:18 * author king **/ Service public class CommentService { //注入dao Autowired private CommentRepository commentRepository; /** * 保存一个评论 */ public void saveComment(Comment comment) { //如果需要自定义主键可以在这里指定主键如果不指定主键MongoDB会自动生成主键 //设置一些默认初始值。。。 //调用dao commentRepository.save(comment); } /** * 更新评论 */ public void updateComment(Comment comment) { //调用dao commentRepository.save(comment); } /** * 根据id删除评论 */ public void deleteCommentById(String id) { //调用dao commentRepository.deleteById(id); } /** * 查询所有评论 */ public ListComment findCommentList() { //调用dao return commentRepository.findAll(); } /** * 根据id查询评论 */ public Comment findCommentById(String id) { //调用dao return commentRepository.findById(id).get(); } } 3新建Junit测试类测试保存和查询所有 com.king.article.service.CommentServiceTest package com.king.article.service; import com.king.article.po.Comment; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.time.LocalDateTime; import java.util.List; SpringBootTest public class CommentServiceTest { Autowired private CommentService commentService; /** * 保存一条记录 */ Test public void testSaveComment() throws Exception { Comment comment new Comment(); comment.setArticleid(100000); comment.setContent(测试添加的数据); comment.setCreatedatetime(LocalDateTime.now()); comment.setUserid(1003); comment.setNickname(凯撒大帝); comment.setState(1); comment.setLikenum(0); comment.setReplynum(0); commentService.saveComment(comment); // 在查询一下这条记录这里获取id的方式和Mybatis Plus一样直接从实体类中获取即可 Comment commentById commentService.findCommentById(comment.getId()); System.out.println(commentById); } /** * 更新一条记录 */ Test public void testUpdateComment() throws Exception { // Comment comment new Comment(); // comment.setId(1); // comment.setNickname(张三); // 上面的方式会将其他字段变为空所以可以先查询出来再更新对应字段 Comment comment commentService.findCommentById(1); comment.setNickname(张三); // 更新这条记录 commentService.updateComment(comment); // 打印一下这条记录 Comment commentById commentService.findCommentById(comment.getId()); System.out.println(commentById); } /** * Method: deleteCommentById(String id) */ Test public void testDeleteCommentById() throws Exception { commentService.deleteCommentById(1); } /** * Method: findCommentList() */ Test public void testFindCommentList() throws Exception { ListComment commentList commentService.findCommentList(); System.out.println(commentList); } /** * 通过id查询一条记录 */ Test public void testFindCommentById() throws Exception { Comment commentById commentService.findCommentById(1); System.out.println(commentById); } } 这里需要注意如果是MongoDB 6以上的版本可能打印不出来这里可能有像MySQL中MVCC之类的同学我换成4版本后就可以正常打印出来了 6.7、根据上级ID查询文章评论的分页列表 1CommentRepository新增方法定义 /** * 分页查询这里的名字要根据提示来不能写错不然会生成失败 */ PageComment findByUserid(String userid, Pageable pageable); 2CommentService新增方法 /** * 根据父id查询分页列表 * param userid * param page 页码 * param size 页数 */ public PageComment findCommentListPageByUserid(String userid,int page ,int size){ return commentRepository.findByUserid(userid, PageRequest.of(page-1,size)); } 测试 Test void testFindCommentListPageByParentid() { PageComment pages commentService.findCommentListPageByUserid(1003, 1, 3); // 打印有多少条记录 System.out.println(pages.getTotalElements()); ListComment contentList pages.getContent(); // 将所有的记录都打印出来 contentList.forEach(System.out::println); } 6.8、MongoTemplate实现评论点赞 我们看一下以下点赞的临时示例代码 CommentService 新增updateThumbup方法 /** * 点赞-效率低 * param id */ public void updateCommentThumbupToIncrementingOld(String id){ Comment comment commentRepository.findById(id).get(); comment.setLikenum(comment.getLikenum()1); commentRepository.save(comment); } 以上方法虽然实现起来比较简单但是执行效率并不高因为我只需要将点赞数加1就可以了没必要查询出所有字段修改后再更新所有字 段。(蝴蝶效应) 我们可以使用MongoTemplate类来实现对某列的操作。 1修改CommentService //注入MongoTemplate Autowired private MongoTemplate mongoTemplate;/** * 点赞数1 * param id */ public void updateCommentLikenum(String id) { //查询对象 Query query Query.query(Criteria.where(_id).is(id)); //更新对象 Update update new Update(); //局部更新相当于$set // update.set(key,value) //递增$inc // update.inc(likenum,1); update.inc(likenum); //参数1查询对象 //参数2更新对象 //参数3集合的名字或实体类的类型Comment.class mongoTemplate.updateFirst(query, update, comment); }2测试用例 Test void testupdateCommentLikenum() { // 更新之前 System.out.println(commentService.findCommentById(2)); commentService.updateCommentLikenum(2); // 更新之后 System.out.println(commentService.findCommentById(2)); }测试结果可以看到数据已经增长了 更多的命令可以自行进行查看这里贴一下API的地址 菜鸟教程Spring-data MongoDB官方文档
http://www.zqtcl.cn/news/414363/

相关文章:

  • 服装 营销型网站案例网站建设资料需要公司提交的吗
  • 网站权重高 做别的关键词怎么查看网站是否被百度收录
  • 沈阳网站开发培训多少钱广州做网站的公司哪家好
  • 宁波江北建设局网站建筑室内设计公司
  • 辽宁网站seo做网站的不给ftp
  • 南宁seo网站排名优化公司电商主图一键生成免费
  • 宁波论坛建站模板wordpress发布公告
  • 电子政务门户网站建设汇报班级优化大师官网登录
  • 做网站购买什么软件c 购物网站开发流程
  • 阿里云做网站送服务器赣州英文网站建设
  • 网站备案号官网黄山网站建设哪家好
  • 鞍山做网站排名滁州seo
  • 加关键词的网站seo服务外包公司
  • 大丰建站研究网站建设
  • 网站建设维护教程聊城做网站推广地方
  • 郑州七彩网站建设公司怎么样国内老牌的注册代理
  • 衡水外贸网站建设临清轴承网站建设
  • 上街郑州网站建设网站管理建设的需求分析
  • 厦门网站建设策划网站推广的常用方法有哪些
  • 做电脑图标的网站上海定制网站建设公司哪家好
  • 重庆seo网站推广工具济南网页设计师招聘信息
  • 甘肃永靖建设住建局网站深圳网络广告推广公司
  • 台州企业网站搭建电话厦门学网站建设
  • 做易经网站做网站布为网
  • 高端定制开发网站可以做网站的网络
  • 局政务网站建设管理工作总结wordpress ks主题
  • 网站集约化建设的意义网页制作成app
  • 建设银行大厂支行网站专业的营销型网站建设公司
  • 询盘网站苏州建设银行招聘网站
  • 制作网站图片手机网站跳转