RESTHeart那件小事-1

由于本周比较忙,所以打算就简单介绍一下关于RESTHeart 的一些内容,主要包括它的安装和查询文档的API,会有一些简单的示例。主要步骤来自于RESTHeart官网。

00:00/00:00

什么是RESTHeart?

RESTHeart是基于Java的、构建在MongoDB数据库之上的Web API服务器。简单说来,它就是一个桥,提供了一个接口,能够让第三方(例如,jquery或浏览器)通过发送符合要求的请求来获取对应的响应数据,使得操作MongoDB变得非常简单。

安装 RESTHeart

预先准备

涉及到的软件或服务:

大多数工作都需要使用命令行完成。

安装Java和MongoDB

针对特定的操作系统安装好Java 8MongoDB,确保二进制文件已经正确执行。可以通过运行下面的命令来检查是否已经正确安装(输出可能会根据Java版本和操作系统版本变化):

  1. $ java -version
  2. java version "1.8.0_66"
  3. Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
  4. Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
  5. $ mongod --version
  6. db version v3.0.7

RESTHeart已经在MongoDB 2.4以后的版本中测试通过。

安装RESTHeart

只需要解压目标文件夹中下载好的包即可:
你只需要关注两个文件:

  • restheart.jar
  • etc/restheart.yml <- 配置文件示例

启动MongoDB

为了简单起见,我们启动MongoDB的时候不启动授权。(实际上教程也提供了安全验证的指南)。
我们可以通过在命令行运行mongod命令启动MongoDB。配置默认使用/data/db文件夹存储数据,因此我们必须在之前创建好该目录。如果我们不想使用默认的数据目录(例如,/data/db),使用--dbpath选项来指定数据目录:mongod --dbpath <path to data directory>。如果希望在后台运行MongoDB进程的话,使用--fork参数:mongod --fork --syslog

  1. $ mongod --fork --syslog
  2. about to fork child process, waiting until server is ready for connections.
  3. forked process: 11471
  4. child process started successfully, parent exiting
  5. MongoDB启动之后,默认监听 127.0.0.1:27017 的连接。

启动RESTHeart服务器

通过在命令行输入java -server -jar restheart.jar来运行RESTHeart服务器。这样会使用默认的配置启动,适用于MongoDB在本地默认端口运行、不需要认证的情况。
一些配置文件的约定:可以通过指定配置文件作为参数选择不同的配置选项。配置文件可以指定任何选项来覆盖默认值:通过这种方式,我们就不必要在配置文件中指定所有可能的选项。

LinuxOSXSolaris系统中,我们可以将RESTHeart运行为一个守护进程java -server -jar restheart.jar --fork。注意:这将会强制关闭控制台日志和开启文件日志,而不用考虑指定的日志配置选项。例如:

  1. $ java -jar restheart.jar
  2. 14:01:09.968 [main] INFO org.restheart.Bootstrapper - Starting RESTHeart
  3. 14:01:09.971 [main] INFO org.restheart.Bootstrapper - version 2.0.0
  4. 14:01:09.978 [main] INFO org.restheart.Bootstrapper - Logging to file /var/folders/yx/mgksqtzn41j41xdnv74snjpc0000gn/T/restheart.log with level INFO
  5. 14:01:09.978 [main] INFO org.restheart.Bootstrapper - Logging to console with level INFO
  6. 14:01:10.275 [main] INFO org.restheart.Bootstrapper - MongoDB connection pool initialized
  7. 14:01:10.275 [main] INFO org.restheart.Bootstrapper - MongoDB version 3.2.0
  8. 14:01:10.276 [main] WARN org.restheart.Bootstrapper - ***** No Identity Manager specified. Authentication disabled.
  9. 14:01:10.277 [main] WARN org.restheart.Bootstrapper - ***** No access manager specified. users can do anything.
  10. 14:01:10.277 [main] INFO org.restheart.Bootstrapper - Token based authentication enabled with token TTL 15 minutes
  11. 14:01:10.593 [main] INFO org.restheart.Bootstrapper - HTTPS listener bound at 0.0.0.0:4443
  12. 14:01:10.593 [main] INFO org.restheart.Bootstrapper - HTTP listener bound at 0.0.0.0:8080
  13. 14:01:10.595 [main] INFO org.restheart.Bootstrapper - Local cache for db and collection properties enabled with TTL 1000 msecs
  14. 14:01:10.595 [main] INFO org.restheart.Bootstrapper - Local cache for schema stores not enabled
  15. 14:01:10.766 [main] INFO org.restheart.Bootstrapper - URL / bound to MongoDB resource *
  16. 14:01:10.976 [main] INFO org.restheart.Bootstrapper - Embedded static resources browser extracted in /var/folders/yx/mgksqtzn41j41xdnv74snjpc0000gn/T/restheart-4469244188076444924
  17. 14:01:10.999 [main] INFO org.restheart.Bootstrapper - URL /browser bound to static resources browser. Access Manager: false
  18. 14:01:11.246 [main] INFO org.restheart.Bootstrapper - Pid file /var/folders/yx/mgksqtzn41j41xdnv74snjpc0000gn/T/restheart-0.pid
  19. 14:01:11.246 [main] INFO org.restheart.Bootstrapper - RESTHeart started

我们将会使用HAL格式和嵌入的HAL浏览器来进行检测。HAL浏览器运行我们使用普通的Web浏览器来操作数据API。

开启MongoDB的认证

本部分以MongoDB3.2为例。对于其它版本,安全配置是相似的,但略有不同。可以查阅MongoDB官方文档。

使用验证的方式启动MongoDB,然后使用在同一个操作系统上运行的客户端连接到MongoDB实例。同样地,我们可以在后台进程运行MongoDB,使用--fork参数:

  1. $ mongod --fork --syslog --auth
  2. $ mongo

接下来,我们会使用MongoDB的超级用户角色root——能够提供对所有资源的所有操作的用户。然而,最佳实践是使用一个有严格权限控制的MongoDB用户。例如,限制该用户只能对某个单一的数据库进行只读操作。可以查阅MongoDB的认证部分文献来接更多信息。

创建admin用户,不同版本有所不同:

  1. > use admin
  2. > db.createUser({
  3. user: "admin",
  4. pwd: "changeit",
  5. roles:[ "root" ]
  6. })

我们需要在RESTHeart的配置文件中提供MongoDB用户认证的证书。接下来,我们使用RESTHeart下载包中的restheart.yml作为示例配置文件(可以在etc文件夹中找到):

  1. $ vi etc/restheart.yml

找到并修改下面的部分,包括用户名、密码和授权的数据库(MongoDB用户定义的数据库,在本示例中为admin):

  1. mongo-uri: mongodb://admin:changeit@127.0.0.1/?authSource=admin

现在,使用指定的配置文件启动RESTHeart:

  1. $ java -server -jar restheart.jar etc/restheart.yml

可以打开浏览器测试连接:http://127.0.0.1:8080/browser
注意:示例的配置文件etc/restheart.yml也启动了RESTHeart安全验证。打开浏览页面之后,将会要求我们进行验证。我们可以使用在etc/security.yml文件中定义的一个认证来进行验证(例如,用户名为a,密码为a)。

通过TLS/SSL连接RESTHeartMongoDB

MongoDB客户端可以使用TLS/SSL来对连接到mongod和mongos的实例进行加密。按照下面的步骤来配置 RESTHeartTLS/SSL

  • 使用keytool来创建keystore来导入mongod使用的公共证书(keytool是用来管理秘钥keystore的Java工具):
  1. $ keytool -importcert -file mongo.cer -alias mongoCert -keystore rhTrustStore
  2. # asks for password, use "changeit"
  • restheart.yml配置文件的mongo-uri选项中指定ssl选项:
  1. mongo-uri: mongodb://your.mongo-domain.com?ssl=true
  • 使用下面的选项启动restheart
  1. $ java -server -Djavax.net.ssl.trustStore=rhTrustStore -Djavax.net.ssl.trustStorePassword=changeit -Djavax.security.auth.useSubjectCredsOnly=false -jar restheart.jar restheart.yml

使用合适权限进行MongoDB认证

在上面的示例中,为了简单,我们使用了一个拥有root角色的MongoDB用户。允许RESTHeart在任何MongoDB资源上执行任何命令。而在生产系统上,需要一个非常强的安全隔离。为了实现这个目标,最佳实践为:
– 使用mongo-mounts配置权限来限制暴露给RESTHeart的资源
– 使用一个恰当角色的MongoDB用户,在相应的数据库中readreadWirte

下面的示例中,创建了一个拥有合角色的MongoDB用户对数据库db1db2db3上进行只读操作:

  1. > use admin
  2. > db.createUser({user: "mongousr",
  3. pwd: "secret",
  4. roles: [{role: "readWrite", db: "db1"},
  5. {role: "readWrite", db: "db2"},
  6. {role: "read", db: "db3"}
  7. ]})

如果需要罗列数据库的话,需要listDatabases权限。这个权限通过readWriteAnyDatabase角色赋予或者你可以创建一个自定义的角色。如果需要删除一个数据库的话,需要dropDatabase权限。这个权限通过dbAdmin角色赋予或者你可以创建一个自定义的角色。

启动RESTHeart之后,我们就可以使用相应的API进行MongoDB的相关操作了。接下来主要介绍查询文档的相关操作。

查询文档

在RESTHeart中, GET 集合资源请求 (GET /db/coll)从集合中检索文档作为嵌入资源。

示例:

检索某个集合的前100个文档:

  1. 请求:
  2. GET /test/coll?pagesize=100&np
  1. 响应(忽略头文件):
  2. HTTP/1.1 200 OK
  3. ...
  4. {
  5. "_embedded": {
  6. "rh:doc": [
  7. { <DOC1> }, { <DOC2> }, { <DOC3> }, ..., { <DOC100> }
  8. ]
  9. },
  10. "_returned": 100
  11. }

默认排序:查询参数np(No Properties)过滤掉响应中的排序集合属性。
文档的默认排序为:按照_id降序排列。通常情况下,文档的_id类型为ObjectId,因此,默认会按照创建时间对文档进行排序(ObjectId的大多数位中包含一个时间戳)。

过滤

filter查询参数可以指定返回文档的条件,filter的参数值可以是任何mongodb查询。

注意:系统属性(RESTHeart自动处理以_开头的属性)不受这个选项的影响。

示例

返回title字段以”Star Trek”开头的文档:

  1. GET /test/coll?filter={'title':{'$regex':'(?i)^STAR TREK.*'}}

这个查询使用mongodb $regex 操作符,其中i选项为非大小写敏感,标题字段匹配以字符串”Star Trek”开头的文档。
返回title字段以”Star Trek”开头并且publishing_data晚于2015年9月4日早上8点的文档:

  1. GET /test/coll?filter={'$and':[{'title': {'$regex':'(?i)^STAR TREK.*'}, {'publishing_date':{'$gte':{'$date':'2015-09-04T08:00:00Z'}}}]}
  2. or
  3. GET /test/coll?filter={'title':{'$regex':'(?i)^STAR TREK.*'}&filter={'publishing_date':{'$gte':{'$date':'2015-09-04T08:00:00Z'}}}

多个过滤参数:注意上面示例的第二种形式,如果指定了多个过滤查询参数,那么它们在逻辑上等同于 AND 操作符。这个选项在基于安全许可的路径连接上非常有用。例如,下面的许可可以与基于简单文件的存取管理器来限制用户读取集合,只在author属性指定一个过滤器等于他们的用户名。

  1. regex[pattern="/test/coll/\?.*filter={'author':'(.*?)'}.*", value="%R", full-match=true] and equals[%u, "${1}"]

计数

指定count查询参数,RESTHeart返回:
_size参数表示集合中的文档总数
_total_pages参数表示所有的页数。它也会返回last链接,例如:跳转到最后一个页面的链接到_links。分页链接(首页、末页、下一页、前一页)以hal full的模式返回。

注意count会对文档进行两次查询:一次用于统计,一次用于真正检索数据,这可能会影响性能。

分页

嵌入文档都会被分页,例如:每次请求只会返回集合文档的子集。返回的文档数目通过pagesize查询参数来控制,默认值是100,最大值是1000。返回的页面通过page查询参数进行指定。分页链接(首页、末页、下一页、前一页)以hal full的模式返回。

例如,返回第2029个文档(第3页):

  1. 请求
  2. GET /test/coll?count&page=3&pagesize=10&hal=f&np
  1. 响应(忽略头文件)
  2. HTTP/1.1 200 OK
  3. ...
  4. {
  5. "_embedded": {
  6. "rh:doc": [
  7. { <DOC30> }, { <DOC31> }, ... { <DOC39> }
  8. ]
  9. }
  10. "_returned": 10,
  11. "_size": 343
  12. "_total_pages": 35
  13. }

排序

排序由sortby查询参数控制。注意:文档不能根据系统属性进行排序(RESTHeart自动处理以_开头的属性)。

sort_by 简化形式

sort_by 简化形式为:

  1. sort_by=[+|-]<fieldname>

其中,+表示递增,-表示递减。
多个查询属性:使用多个sort_by查询参数来指定多个排序参数。

  1. GET /db/coll?sort_by=name&sort_by=-age

sort_byjson表达式形式

sort_by也可以为MongoDBsort表达式,从2.0.1开始支持的。

  1. sort_by={"field": 1}

示例

根据date升序排列

  1. GET /test/coll?sort_by=date
  2. GET /test/coll?sort_by={"date":1}

根据date降序排列

  1. GET /test/coll?sort_by=-date
  2. GET /test/coll?sort_by={"date":-1}

根据date降序排列、title升序排列

  1. GET /test/coll?sort_by=-date&sort_by=title
  2. GET /test/coll?sort_by={"date":-1, "title":1}

根据检索分数进行排列(针对文本检索,只能使用json表达式形式)

  1. // create a text index
  2. PUT /test/coll/_indexes/text {"keys": {"title": "text }}
  3. // sort by {"$meta": "textScore"}
  4. GET /test/coll?filter={"$text":{"$search":"a search string"}}&keys={"title":1,"score":{"$meta":"textScore"}}&sort_by={"score":{"$meta":"textScore"}}

映射

映射限制了所有匹配文档的返回字段,指定包含或排除的字段。通过keys查询参数完成。可以使用多个keys查询参数来指定映射多个字段。

注意:系统属性(RESTHeart自动处理以_开头的属性)不受这个选项的影响。

示例

只返回title属性

  1. GET /test/coll?keys={'title':1}

返回除title外的其它所有属性

  1. GET /test/coll?keys={'title':0}

只返回titlesummary属性

  1. GET /test/coll?keys={'title':1}&keys={'summary':1}

可以使用点来指定一个对象中的字段,例如假设titlesummary字段都是header对象的一部分:

  1. GET /test/coll?keys={'header.title':1}&keys={'header.summary':1}

总结

使用RESTHeart操作MongoDB是非常方便的。毕竟,我觉得RESTful应该是一个大趋势,这些简化工作是程序媛们的福音。由于时间有限,只是根据文档粗略地介绍了下安装和查询文档的API和示例。下周会更新比较重要的安全和写入。

打赏
微信扫一扫支付
微信logo微信扫一扫, 打赏作者吧~

mickey

记录生活,写给几十年后的自己。