Java_MongoDB-灵活文档型数据库

MongoDB简介

        MongoDB是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是 NoSQL 数据库产品中的一种。是最像关系型数据库(MySQL )的非关系型数据库。
        它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫 BSON ,所以它既可以存储比较复杂的数据类型,又相当的灵活。
        MongoDB中的记录是一个文档,它是一个由字段和值对( field:value )组成的数据结构。 MongoDB 文档类似于 JSON 对象,即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。

业务应用场景:

        传统的关系型数据库(如MySQL ),在数据操作的 三高 需求以及应对 Web2.0 的网站需求面前,显得力不从心。
        “三高 需求:
                • High performance - 对数据库高并发读写的需求。
                • Huge Storage - 对海量数据的高效率存储和访问的需求。
                • High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求。
MongoDB 可应对 三高 需求。

具体的应用场景如:

1 )社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能。
2 )游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、高效率存储和访问。
3 )物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将
订单所有的变更读取出来。
4 )物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析。
5 )视频直播,使用 MongoDB 存储用户信息、点赞互动信息等。
这些应用场景中,数据操作方面的共同特点是:
1 )数据量大
2 )写入操作频繁(读写都很频繁)
3 )价值较低的数据,对事务性要求不高
对于这样的数据,我们更适合使用 MongoDB 来实现数据的存储。

体系结构:

MySQL和MongoDB对比

如何下载使用:

       下载网址: Try MongoDB Atlas Products | MongoDB

注:

        MongoDB的版本命名规范如:x.y.z;

        y为奇数时表示当前版本为开发版,如:1.5.2、4.1.13;

        y为偶数时表示当前版本为稳定版,如:1.6.3、4.0.10;

        z是修正版本号,数字越大越好。

解压安装包后,在bin同级目录下,手动建立一个目录用于存放数据文件,如 data/db

1.在 bin 目录中打开命令行提示符,输入如下命令:

mongod --dbpath=..\data\db

结果:

2.在 bin 目录下新打开一个cmd窗口,输入如下命令:

mongo

结果:

3.验证:查看已经有的数据库,输入如下命令

show databases

结果:

这三个数据库是系统自带的数据库,出现这三个数据库说明连接没有问题。

数据库名可以是满足以下条件的任意UTF-8字符串。

        不能是空字符串("")。

        不得含有' '(空格)、.、$、/、\和\0 (空字符)。

        应全部小写。 最多64字节。

有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。

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

        local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合

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

图形化界面:

        这里我使用的是compass图形化界面,下载地址:https://www.mongodb.com/download-center/v2/compass?initial=true,下载并解压后执行里面的 MongoDBCompassCommunity.exe 文件即可。

操作方法

数据库操作:

创建/选择:

选择和创建数据库的语法格式:

use 数据库名称

如果数据库不存在则自动创建,例如,以下语句创建 spitdb 数据库:

use articledb

查看有权限查看的所有的数据库命令

show dbs

        或

show databases

        注意: 在 MongoDB 中,集合只有在内容插入后才会创建! 就是说,创建集合(数据表)后要再插入一个文档(记录),集合才会真正创建。

查看:

查看当前正在使用的数据库命令

db

        MongoDB 中默认的数据库为 test,如果你没有选择数据库,集合将存放在 test 数据库中。

删除:

MongoDB 删除数据库的语法格式如下:

db.dropDatabase()

        提示:主要用来删除已经持久化的数据库

集合操作:

        集合,类似关系型数据库中的表。 可以显示的创建,也可以隐式的创建。

集合的命名规范:

        集合名不能是空字符串""。

        集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。

        集合名不能以"system."开头,这是为系统集合保留的前缀。

        用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。

集合的显式创建(了解):

基本语法格式:

db.createCollection(name)

name: 要创建的集合名称

查看当前库中的表:

show collections

        或

show tables

集合的隐式创建:

        当向一个集合中插入一个文档的时候,如果集合不存在,则会自动创建集合。 详见 文档的插入 章节。 提示:通常我们使用隐式创建文档即可。

集合的删除:

集合删除语法格式如下:

db.collection.drop()

        或

db.集合名.drop()
返回值:

如果成功删除选定集合,则 drop() 方法返回 true,否则返回 false。

文档操作:

文档插入:

1)单个文档插入
        使用insert() save() 方法向集合中插入文档,语法如下:
db.collection.insert(
<document or array of documents>,
{
writeConcern: <document>,
ordered: <boolean>
}
)
示例:
        要向comment 的集合 ( ) 中插入一条测试数据:
db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明
媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null})
提示:
1 comment 集合如果不存在,则会隐式创建
2 mongo 中的数字,默认情况下是 double 类型,如果要存整型,必须使用函数 NumberInt( 整型数字 ) ,否则取出来就有问题了。
3 )插入当前日期使用 new Date()
4 )插入的数据没有指定 _id ,会自动生成主键值
5 )如果某字段没值,可以赋值为 null ,或不写该字段。
成功执行后会显示结果:
WriteResult({ "nInserted" : 1 })
注意:
1. 文档中的键 / 值对是有序的。
2. 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档 )
3. MongoDB 区分类型和大小写。
4. MongoDB 的文档不能有重复的键。
5. 文档的键是字符串。除了少数例外情况,键可以使用任意 UTF-8 字符。
文档键命名规范:
·键不能含有\0 ( 空字符 ) 。这个字符用来表示键的结尾。
·.和$ 有特别的意义,只有在特定环境下才能使用。
· 以下划线"_"开头的键是保留的 ( 不是严格要求的 )
2)批量插入
语法:
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"}
]);
提示:
1)插入时指定了 _id ,则主键就是该值。
2)如果某条数据插入失败,将会终止插入,但已经插入成功的数据不会回滚掉。
3)因为批量插入由于数据较多容易出现失败,因此,可以使用 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);
}

文档查询:

1)查询所有
如果我们要查询 spit 集合的所有文档,我们输入以下命令:
db.comment.find()
或
db.comment.find({})
        每条文档会有一个叫_id 的字段,这个相当于我们原来关系数据库中表的主键,当你在插入文档记录时没有指定该字段,MongoDB会自动创建,其类型是 ObjectID类型。如果我们在插入文档记录时指定该字段也可以,其类型可以是 ObjectID 类型,也可以是 MongoDB 支持的任意类型。
(2)条件查询
比如我想查询 userid 1003 的记录:
db.comment.find({userid:'1003'})
(3)查询一个
查询用户编号是 1003 的记录,但只最多返回符合条件的第一条记录:
db.comment.findOne({userid:'1003'})
(4)投影查询
如果要查询结果返回部分字段,则需要使用投影查询(不显示所有字段,只显示指定的字段)。
如:查询结果只显示 _id userid nickname :
db.comment.find({userid:"1003"},{userid:1,nickname:1})
{ "_id" : "4", "userid" : "1003", "nickname" : "凯撒" }
{ "_id" : "5", "userid" : "1003", "nickname" : "凯撒" }
默认 _id 会显示。
如:查询结果只显示 userid nickname ,不显示 _id
db.comment.find({userid:"1003"},{userid:1,nickname:1,_id:0})
{ "userid" : "1003", "nickname" : "凯撒" }
{ "userid" : "1003", "nickname" : "凯撒" }
再例如:查询所有数据,但只显示 _id userid nickname :
db.comment.find({},{userid:1,nickname:1})

文档更新:

1)覆盖的修改

如果我们想修改_id1的记录,点赞量为1001,输入以下语句:

db.comment.update({_id:"1"},{likenum:NumberInt(1001)})
执行后,我们会发现,这条文档除了 likenum 字段其它字段都不见了。
为了解决这个问题,我们需要使用修改器 $set 来实现局部修改。
2)局部修改
我们想修改 _id 2 的记录,浏览量为 889 ,输入以下语句:
db.comment.update({_id:"2"},{$set:{likenum:NumberInt(889)}})
3)批量的修改
更新所有用户为 1003 的用户的昵称为 凯撒大帝
//默认只修改第一条数据
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒2"}})
//修改所有符合条件的数据
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒大帝"}},{multi:true})
        如果不加后面的参数,则只更新符合条件的第一条记录
4)列值增长的修改
如果我们想实现对某列值在原有值的基础上进行增加或减少,可以使用 $inc 运算符来实现。
需求:对 3 号数据的点赞数,每次递增 1
db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})

文档删除:

删除文档的语法结构:
db.集合名称.remove(条件)
以下语句可以将数据全部删除,请慎用
db.comment.remove({})
如果删除 _id=1 的记录,输入以下语句
db.comment.remove({_id:"1"})

分页查询:

(1)统计查询

统计comment集合的所有的记录数:

db.comment.count()
统计 userid 1003 的记录条数:
db.comment.count({userid:"1003"})
        默认情况下 count() 方法返回符合条件的全部记录条数。
(2)分页列表查询
如果你想返回指定条数的记录,可以在 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)排序查询

userid降序排列,并对访问量进行升序排列:

db.comment.find().sort({userid:-1,likenum:1})
提示:

        skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit(),和命令编写顺序无关。

文档的更多查询:

(1)正则的复杂条件查询
例如,我要查询评论内容包含 开水 的所有文档,代码如下:
db.comment.find({content:/开水/})
如果要查询评论的内容中以 专家 开头的,代码如下:
db.comment.find({content:/^专家/})
(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)包含查询
包含使用 $in 操作符。 示例:查询评论的集合中 userid 字段包含 1003 1004 的文档
db.comment.find({userid:{$in:["1003","1004"]}})
不包含使用 $nin 操作符。 示例:查询评论集合中 userid 字段不包含 1003 1004 的文档
db.comment.find({userid:{$nin:["1003","1004"]}})
(4)条件连接查询
如果需要查询 同时满足 两个以上条件,需要使用 $and 操作符将条件进行关联。(相 当于 SQL and ) 格式为:
$and:[ { },{ },{ } ]
示例:查询评论集合中 likenum 大于等于 700 并且小于 2000 的文档:
db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})
如果两个以上条件之间是 或者 的关系,我们使用 操作符进行关联,与前面 and 的使用方式相同 格式为:
$or:[ { },{ },{ } ]
示例:查询评论集合中 userid 1003 ,或者点赞数小于 1000 的文档记录:
db.comment.find({$or:[ {userid:"1003"} ,{likenum:{$lt:1000} }]})

常用命令:

选择切换数据库: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 可以使用该索引限制必须检查的文档数。
        索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB 还可以使用索引中的排序返回排序结果。
        MongoDB索引使用 B 树数据结构(确切的说是 B-Tree MySQL B+Tree)

索引类型:

(1)单字段索引:

        MongoDB支持在文档的单个字段上创建用户定义的升序 / 降序索引,称为单字段索引( Single Field Index )。
        对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB 可以在任何方向上遍历索引

(2)复合索引:

        MongoDB还支持多个字段的用户定义索引,即复合索引( Compound Index )。
        复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: - 1 } 组成,则索引首先按 userid 正序排序,然后在每个userid 的值内,再在按 score 倒序排序。

(3)其他索引:

①地理空间索引( Geospatial Index ):
        为了支持对地理空间坐标数据的有效查询,MongoDB 提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。
②文本索引( Text Indexes ):
        MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如 “the” “a” “or” ),而将集合中的词作为词干,只存储根词。
③哈希索引( Hashed Indexes ):
        为了支持基于散列的分片,MongoDB 提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。

索引操作:

索引查看:

返回一个集合中的所有索引的数组:
db.collection.getIndexes()
例如查看 comment 集合中所有的索引情况:
db.comment.getIndexes()

结果:

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "articledb.comment"
    }
]
        结果中显示的是默认 _id 索引。
        默认_id 索引: MongoDB在创建集合的过程中,在 _id 字段上创建一个唯一的索引,默认名字为 _id_ ,该索引可防止客户端插入两个具有相同值的文档,不能在_id 字段上删除此索引。
        注意:该索引是唯一索引,因此值不能重复,即 _id 值不能重复的。在分片集群中,通常使用 _id 作为片键。

索引创建:

(1)单字段索引示例:对 userid 字段建立索引:
db.comment.createIndex({userid:1})

(2)复合索引:对 userid nickname 同时建立复合(Compound)索引:

db.comment.createIndex({userid:1,nickname:-1})

索引移除:

删除 comment 集合中 userid 字段上的升序索引:
db.comment.dropIndex({userid:1})
所有索引的移除:
db.collection.dropIndexes()

        若要删除文本索引,需要指定索引名称

索引使用:

(1)执行计划
        分析查询性能(Analyze Query Performance )通常使用执行计划(解释计划、 Explain Plan )来查看查询的情况,如查询耗费的时间、是否基于索引查询等。
        那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。
语法:
db.collection.find(query,options).explain(options)

示例:查看根据userid查询数据的情况:

db.comment.find({userid:"1003"}).explain()

结果:

关键点看: "stage" : "COLLSCAN", 表示全集合扫描,
                   "stage" : "IXSCAN" , 基于索引的扫描
(2)涵盖的查询
        当查询条件和查询的投影仅包含索引字段时,MongoDB 直接从索引返回结果,而不扫描任何文档或将文档带入内存。 这些覆盖的查询可以非常有效。
示例:
db.comment.find({userid:"1003"},{userid:1,_id:0})

结果:

{ "userid" : "1003" }
{ "userid" : "1003" }

实战:

        完成课程评论功能

功能:

        1)基本增删改查 API
        2)根据课程id查询评论
        3)评论点赞

表结构:

技术选型:

mongodb-driver (了解)
mongodb-driver mongo 官方推出的 java 连接 mongoDB 的驱动包,相当于 JDBC 驱动。我们通过一个入门的案例来了解 mongodb-driver的基本使用。
★SpringDataMongoDB
SpringData 家族成员之一,用于操作 MongoDB 的持久层框架,封装了底层的 mongodb-driver
官网主页: https://projects.spring.io/spring-data-mongodb/
我们采用 SpringDataMongoDB 框架。

环境搭建:

1)搭建项目工程articlepom.xml引入依赖:

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

2)创建application.yml

spring:
#数据源配置
data:
mongodb:
# 主机地址
host: 127.0.0.1
# 数据库
database: articledb
# 默认端口是27017
port: 27017
#也可以使用uri连接
#uri: mongodb://192.168.40.134:27017/articledb

代码编写:

①编写实体类

//把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。
//@Document(collection="mongodb 对应 collection 名")
// 若未加 @Document ,该 bean save 到 mongo 的 comment collection
// 若添加 @Document ,则 save 到 comment collection
@Data
@Document(collection="comment")//可以省略,如果省略,则默认使用类名小写映射集合
//复合索引
// @CompoundIndex( def = "{'userid': 1, 'nickname': -1}")
public class Comment implements Serializable {
    //主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
    @Id
    private String id;//主键
    //该属性对应mongodb的字段的名字,如果一致,则无需该注解
    @Field("content")
    private String content;//评论内容
    private Date publishtime;//发布日期
    //添加了一个单字段的索引
    @Indexed
    private String userid;//发布人ID
    private String nickname;//昵称
    private LocalDateTime createdatetime;//评论的日期时间
    private Integer likenum;//点赞数
    private Integer replynum;//回复数
    private String state;//状态
    private String parentid;//上级ID
    private String articleid;
    //getter and setter.....
}

②课程评论的基本增删改查:

1)创建数据访问接口 cn.itcast.article包下创建dao包,包下创建接口
//评论的持久层接口
public interface CommentRepository extends MongoRepository<Comment,String> {
}
2)创建业务逻辑类 cn.itcast.article包下创建service包,包下创建类
//评论的业务层
@Service
public class CommentService {
    //注入dao
    @Autowired
    private CommentRepository commentRepository;
    /**
    * 保存一个评论
    * @param comment
    */
    public void saveComment(Comment comment){
        //如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
        //设置一些默认初始值。。。
        //调用dao
        commentRepository.save(comment);
    }
    /**
    * 更新评论
    * @param comment
    */
    public void updateComment(Comment comment){
        //调用dao
        commentRepository.save(comment);
    }
    /**
    * 根据id删除评论
    * @param id
    */
    public void deleteCommentById(String id){
        //调用dao
        commentRepository.deleteById(id);
    }
    /**
    * 查询所有评论
    * @return
    */
    public List<Comment> findCommentList(){
        //调用dao
        return commentRepository.findAll();
    }
    /**
    * 根据id查询评论
    * @param id
    * @return
    */
    public Comment findCommentById(String id){
        //调用dao
        return commentRepository.findById(id).get();
    }
}

③根据上级ID查询课程评论的分页列表

1CommentRepository新增方法定义
//根据父id,查询子评论的分页列表
Page<Comment> findByParentid(String parentid, Pageable pageable);
2CommentService新增方法
public Page<Comment> findCommentListPageByParentid(String parentid,int page ,int size){
return commentRepository.findByParentid(parentid, PageRequest.of(page-1,size));
}

④MongoTemplate实现评论点赞

修改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");
    }

        这样就实现了课程评论功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值