R语言中连接数据库——Mongodb

R语言中连接数据库——Mongodb

一、项目环境

  • 开发工具:RStudio
  • R:3.6.1
  • 相关包:mongolite

二、mongolite 包安装

# 方法一:直接通过CRAN进行安装
install.packages("mongolite")

# 方法二:从github上安装

devtools::install_github("jeroen/mongolite")

三、mongolite 包的使用

library(mongolite)
# 连接mongodb数据库

con <- mongo("mtcars", url = "mongodb://readwrite:test@mongo.opencpu.org:43942/jeroen_test")
# collection:要连接的集合(数据表)的名称。默认为"test"。
# db:要连接的数据库的名称。默认为"test"。
# url:标准URI格式的MongoDB服务器的地址。
# verbose:如果TRUE,发出一些额外的输出
# options:其他连接选项,例如SSL密钥/证书。


# 如果数据表是空的,就自己插入一下
data(mtcars)
con$insert(mtcars)

[注]: 该url参数包含特殊的URI格式,该格式定义服务器地址和其他连接选项。格式如下:

mongodb://[用户名:密码@]数据库地址[:端口号][,数据库地址2[:端口号2],...[/[数据库名称][?其他连接选项]]

具体的url格式可以参考 《Mongo连接字符串手册》

# mongolite的一些具体操作
# 直接输出连接成功后数据库的变量,会输出mongodb常见操作的公式,及使用方法
print(con)
# <Mongo collection> 'mtcars' 
# $aggregate(pipeline = "{}", options = "{\"allowDiskUse\":true}", handler = NULL, pagesize = 1000, iterate = FALSE) 
# $count(query = "{}") 
# $disconnect(gc = TRUE) 
# $distinct(key, query = "{}") 
# $drop() 
# $export(con = stdout(), bson = FALSE, query = "{}", fields = "{}", sort = "{\"_id\":1}") 
# $find(query = "{}", fields = "{\"_id\":0}", sort = "{}", skip = 0, limit = 0, handler = NULL, pagesize = 1000) 
# $import(con, bson = FALSE) 
# $index(add = NULL, remove = NULL) 
# $info() 
# $insert(data, pagesize = 1000, stop_on_error = TRUE, ...) 
# $iterate(query = "{}", fields = "{\"_id\":0}", sort = "{}", skip = 0, limit = 0) 
# $mapreduce(map, reduce, query = "{}", sort = "{}", limit = 0, out = NULL, scope = NULL) 
# $remove(query, just_one = FALSE) 
# $rename(name, db = NULL) 
# $replace(query, update = "{}", upsert = FALSE) 
# $run(command = "{\"ping\": 1}", simplify = TRUE) 
# $update(query, update = "{\"$set\":{}}", filters = NULL, upsert = FALSE, multiple = FALSE)  

四、mongolite 包相关函数

​ 接下来我们就根据官方给我们提供的常见函数表,一个一个进行讲解:

1、$aggregate

# aggregate函数可以说是我使用最多的函数,很多操作都可以用这个函数实现
con$aggregate('[
                  {
                    "$match":{"cyl":4}
                  },
                  {
                    "$limit":3
                  } 
                ]')
# 该代码实现的功能用sql语句实现就是:
# select * from mtcars where cyl = 4 limit 0, 3
SQL 操作/函数mongodb aggregate操作
select * from mtcars where cyl = 4conKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">match" : {“cyl” : 4}} ]')
select cyl as _id from mtcars group by cylconKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">group" : {“_id” : “$cyl”}}]')
select cyl from mtcarsconKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">project“:{”_id" : 0, “cyl” : 1}}]')
select * from mtcars order by cylconKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">sort" : {“cyl” : 1}}]')
select * from mtcars limit 0, 4conKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">limit" : 4}]')
select cyl as _id, count(1) as count from mtcars group by cylconKaTeX parse error: Expected '}', got 'EOF' at end of input: aggregate('[{"group" : {“_id” : “KaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">sum” : 1}}}]')
select cyl as _id, sum(mpg) as sum from mtcars group by cylconKaTeX parse error: Expected '}', got 'EOF' at end of input: aggregate('[{"group" : {“_id”:“KaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">sum”:“$mpg”}}}]')
select * from services, flows inner join services.flow = flows.nameconKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">lookup": {“from” : “flows”,“localField” : “flow”, “foreignField” : “name”, “as” : “flow_detail”}} ]') (没试过,不确定)
select * from mtcars order by rand() limit 20conKaTeX parse error: Expected '}', got 'EOF' at end of input: …nt color="red">sample" : {“size” : 20}}]')

2、$count

# $count()可以输出该数据表中有多少的数据
# 在还不确定数据表大小的时候,可以先用这个函数看一下大小
con$count()
# [1] 32

con$count('{"cyl":4}')
# [1] 11

3、$disconnect

# 断开连接用的
con$disconnect()

4、$distinct

# 去重,返回该字段的唯一值。
con$distinct("mpg")

# 可在后面增加其他条件加以限制。
con$distinct("mpg", '{"cyl":4}')

5、$drop

# 删除数据表(警告:不要拿公司数据库试这个函数)
con$drop()

6、$export

# 将数据以json的形式输出,当bson = TRUE时,它会输出二进制bson格式。
con$export(query = '{"mpg":19.2}')

#{ "_id" : { "$oid" : "5dd29754e9280000e8000fbd" }, "mpg" : 19.199999999999999289, "cyl" : 6.0, "disp" : 167.59999999999999432, "hp" : 123.0, "drat" : 3.9199999999999999289, "wt" : 3.4399999999999999467, "qsec" : 18.300000000000000711, "vs" : 1.0, "am" : 0.0, "gear" : 4.0, "carb" : 4.0, "_row" : "Merc 280" }
#{ "_id" : { "$oid" : "5dd29754e9280000e8000fcc" }, "mpg" : 19.199999999999999289, "cyl" : 8.0, "disp" : 400.0, "hp" : 175.0, "drat" : 3.0800000000000000711, "wt" : 3.8450000000000001954, "qsec" : 17.050000000000000711, "vs" : 0.0, "am" : 0.0, "gear" : 3.0, "carb" : 2.0, "_row" : "Pontiac Firebird" }
# 整理后的json长这样
{
    "_id": {
        "$oid": "5dd29754e9280000e8000fbd"
    },
    "mpg": 19.199999999999999289,
    "cyl": 6.0,
    "disp": 167.59999999999999432,
    "hp": 123.0,
    "drat": 3.9199999999999999289,
    "wt": 3.4399999999999999467,
    "qsec": 18.300000000000000711,
    "vs": 1.0,
    "am": 0.0,
    "gear": 4.0,
    "carb": 4.0,
    "_row": "Merc 280"
}
{
    "_id": {
        "$oid": "5dd29754e9280000e8000fcc"
    },
    "mpg": 19.199999999999999289,
    "cyl": 8.0,
    "disp": 400.0,
    "hp": 175.0,
    "drat": 3.0800000000000000711,
    "wt": 3.8450000000000001954,
    "qsec": 17.050000000000000711,
    "vs": 0.0,
    "am": 0.0,
    "gear": 3.0,
    "carb": 2.0,
    "_row": "Pontiac Firebird"
}

7、$find

# 查询函数,也是一个非常常用的函数,和$aggregate一样都能完成查询的工作
# 但至于哪个查询速度更快,目前没看出来。望大神指教。
con$find(
  query = '{"cyl" : 4}', # 查询条件
  fields = '{"mpg" : true, "cyl" : true, "disp" : true}', # 那些列需要显示出来
  limit = 5, # 查询出几条数据
  skip = 1 # 跳过几条数据,skip = 1 表示跳过一条数据。也就是函数从第二条数据开始查询5条符合条件的函数.
)

#                        _id  mpg cyl  disp
# 1 5dd29754e9280000e8000fbb 24.4   4 146.7
# 2 5dd29754e9280000e8000fbc 22.8   4 140.8
# 3 5dd29754e9280000e8000fc5 32.4   4  78.7
# 4 5dd29754e9280000e8000fc6 30.4   4  75.7
# 5 5dd29754e9280000e8000fc7 33.9   4  71.1

8、$import

# 说明中可以导入json格式的数据,但实际测试没有成功。实际作用为止
#(帮助文档的例子都没法运行成功)
con$import(con, bson = FALSE)


9、$index

# 为数据文件创建索引,来加快数据的查询速度(不知道为啥有时候加了索引反而更慢)
system.time(con$find('{"cyl":5}'))
# 用户 系统 流逝 
# 0.00 0.00 2.47 

con$index(add = '{"qsec":1}')
#   v key._id key.qsec   name                 ns
# 1 2       1       NA   _id_ jeroen_test.mtcars
# 2 2      NA        1 qsec_1 jeroen_test.mtcars

system.time(con$find('{"cyl":5}'))
# 用户 系统 流逝 
# 0.00 0.00 0.73 

con$index(remove = "qsec_1")
#   v _id name                 ns
# 1 2   1 _id_ jeroen_test.mtcars

10、$info

# 输出服务器的信息(如果有的话,例子来自官网)
col$info()
#> List of 4
#>  $ collection: chr "test"
#>  $ db        : NULL
#>  $ stats     : NULL
#>  $ server    :List of 25
#>   ..$ host                     : chr "Jeroens-MBP.fritz.box"
#>   ..$ version                  : chr "4.0.1"
#>   ..$ process                  : chr "mongod"
#>   ..$ pid                      : num 64577
#>   ..$ uptime                   : num 5625
#>   ..$ uptimeMillis             : num 5625324
#>   ..$ uptimeEstimate           : num 5625
#>   ..$ localTime                : POSIXct[1:1], format: "2018-08-09 22:18:01"
#>   ..$ asserts                  :List of 5
#>   ..$ connections              :List of 3
#>   ..$ extra_info               :List of 2
#>   ..$ freeMonitoring           :List of 1
#>   ..$ globalLock               :List of 3
#>   ..$ locks                    :List of 3
#>   ..$ logicalSessionRecordCache:List of 11
#>   ..$ network                  :List of 7
#>   ..$ opLatencies              :List of 3
#>   ..$ opcounters               :List of 6
#>   ..$ opcountersRepl           :List of 6
#>   ..$ storageEngine            :List of 5
#>   ..$ transactions             :List of 3
#>   ..$ wiredTiger               :List of 17
#>   ..$ mem                      :List of 6
#>   ..$ metrics                  :List of 10
#>   ..$ ok                       : num 1

11、$insert

# 插入数据(如果又不小心把数据删了,可以执行这个语句)
data(mtcars)
con$insert(mtcars)

12、$iterate

# 作用不明(待完善)
con$iterate('{"cyl":4}',limit = 2)
#<Mongo iterator> 
# $batch(size = 1000) 
# $json(size = 1000) 
# $one() 
# $page(size = 1000) 

13、$mapreduce

# mapreduce 是一种编程模型,用于大规模数据集(大于1TB)的并行运算。
# 可以将其分为用于映射的 Map 和用于组合的 Reduce。可以根据例子进行简单的理解
con$mapreduce(
      #  map = "function() {emit(key,value);}", 
      # 映射函数 (生成键值对序列,作为 reduce 函数参数)(在函数中调用字段需要用到 this.*)
       map = "function(){emit(Math.floor(this.disp/100)*100, 1)}",
     # reduce = "function(key,values) {return reduceFunction},
      #           {
      #             out: collection,
      #             query: document,
      #             sort: document,
      #             limit: number
      #           }"
      # reduce函数的任务就是将key-values变成key-value,也就是把values数组变成一个单一的值value
       reduce = "function(id, counts){return Array.sum(counts)}"
    
      # 整个函数的作用就是将字段 cyl 进行百分位向下取整,并进行分组统计
   )

[注]: 由于 mapreduce 函数相对与其他函数而言比较不好理解,如果实在没理解的可以查>看下列配图解释,或者查阅菜鸟教程和mongodb官方的解释,网站连接和配图如下:

菜鸟教程:https://www.runoob.com/mongodb/mongodb-map-reduce.html

mongodb官方:https://docs.mongodb.com/manual/reference/command/mapReduce/index.html

在这里插入图片描述


14、$remove

# 删除查询出来的结果

# 删除前
con$find()
con$remove('{"cyl":4}')
# 删除后
con$find()

15、$rename

# 修改集合的名称(也可以修改数据库的,但是比较麻烦)
con$rename("mtcars1")

16、$replace

# 替换数据(在单表的处理上与 update 功能基本相同。但是修改的时候需要将完整的数据输入进去,建议用 update)
con$replace('{"wt": 2.620,"qsec":16.46}',
            '{"mpg": 21,
              "cyl": 6,
              "disp":160,
              "hp":110,
              "drat":3.9,
              "wt":2.00,
              "qsec":16.00,
              "vs":0,
              "am":1,
              "gear":4,
              "carb":4}')

17、$run

# 允许使用最原始的mongodb命令,simplify = TRUE 表示同意简化输出
# 下面的操作用于检查服务器链接是否正常
con$run('{"ping" : 1}')

18、$update

# 更新数据(与 replace 的不同在于,需要叫上 "$set" 来修改部分数据)
con$update('{"wt": 2.875,"qsec":17.02}',
             '{"$set" : {
               "wt":2.62,
               "qsec":16.46}}')

很长一段时间没有在csdn中写文章了,事实上后面自己学习过程中的大部分文档都是在语雀中完成的,基本都是自己写自己看。后续文章都会分享到自己的个人博客上,感兴趣的话可以关注一下。个人博客地址