淘先锋技术网

首页 1 2 3 4 5 6 7

1、MongoDB 简介

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。MongoDB 是由 C++语言编写的,是一个基于分布式文件存储的开源数据库系统。

在高负载的情况下,添加更多的节点,可以保证服务器性能。

MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。

1.1、MongoDB 特性

MongoDB 最吸引人的地方应该就是自由的表结构、MapReduce、分片、副本集,通过这些功能实现海量数据的存储、高效地读写以及数据的分析。

1.1.1、面向文档存储

MongoDB 是面向文档的设计,BSON 更容易以文档真正的形式存储和获取文档,有效地避免了任何映射或特有转换代码的需求,事实上,该特性也使 MongoDB 变得更容易扩展。

BSON 是一个开放标准。BSON 是 JSON 的二进制形式,BSON 版本与相同的 JSON 版本会占用更多的空间,那为什么会使用 BSON 呢,原因是 BSON 更易于遍历。尽管相比 JSON,BSON 需要稍微多一些的磁盘空间,但这并不是问题,因为磁盘很便宜,多占用一些磁盘空间,换来的是更好的查询和索引功能。使用 BSON 的第二个优点在于很容易将 BSON 数据转换成编程语言的原生数据格式。如果以 JSON 方式存储数据,就需要添加一个较高级别的转换,使用简单的二进制格式可以在各种语言中快速构建原生数据结构,而不需要首先对 BSON 进行处理。这将使得代码更简洁。

1.1.2、不支持 JOIN

MongoDB 查询语句不是按照 SQL 的标准来开发的,它围绕 BSON 这种特殊格式的文档型存储模型开发了一套自己的查询体系,这就是现在非常流行的 NoSQL 体系。关系型数据库中常用的 SQL 语句在 MongoDB 中都有对应的解决方案。当然也有例外,MongoDB 不支持 J0IN 语句。我们知道传统关系数据库中 JOIN 操作可能会产生笛卡尔积的虚拟表,消耗较多系统资源,而 MongoDB 的文档对象集合 collection 可以是任何结构,我们可以通过设计较好的数据模型尽量避开这样的操作需求。如果真的需要从多个 collection (表)中检索数据,那我们可以通过多次查询得到。

1.1.3、MapReduce

在关系数据库中经常用到的 group by 等分组聚集函数,在 MongoDB 中也有,而且 MongoDB 提供了更加强大的 MapReduce 方案为海量数据的统计、分析提供了便利。

1.1.4、日志功能

MongoDB 支持日志功能 Journaling,对数据库的增、删、改操作会记录在日志文件中。MongoDB 每 100ms 将内存中的数据刷到磁盘上,如果意外停机,在数据库重新启动时,MongoDB 能通过 Journaiing 日志功能恢复。

1.1.5、副本集

MongoDB 支持副本集,一个副本集在生产环境中最少需要 3 台独立的机器(测试的时候为了方便可能都部署在一台机器上),一台作主节点(primary), —台作次节点(secondary), —台作仲裁节点(只负责选出主节点),备份、自动故障转移,这些特性都是副本集支持的。

1.1.6、自动分片

MongoDB 支持自动分片 Sharding,分片的功能实现海量数据的分布式存储,分片通常与副本集配合起来使用,实现读写分离、负载均衡,当然如何选择片键是实现分片功能的关键。

1.2、MongoDB 数据模型

SQL 术语/概念MongoDB 术语/概念解释/说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引
tablejoins表连接,MongoDB 不支持
primary keyprimary key主键,MongoDB 自动将_id 字段设置为主键

2、下载安装 MongoDB

2.1、配置 yum 源

输入以下命令:

vi /etc/yum.repos.d/mongodb.repo

添加以下内容:

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

2.2、下载 MongoDB

yum -y install mongodb-org

查看版本

mongod --version

查看到版本则说明下载安装成功

3、MongoDB 操作

3.1、启动关闭

启动 MongoDB

systemctl start mongod.service
#非root用户
sudo systemctl start mongod.service

查看启动状态

systemctl status mongod.service

进入 MongoDB 客户端

mongo

关闭 MongoDB

systemctl stop mongod.service

3.2、数据库操作

3.2.1、查看所有数据库

查看所有数据库不会显示没有数据的数据库

show databases
show dbs

3.2.2、创建数据库

如果数据库不存在,则创建数据库,否则切换到指定数据库。

use db_name

3.2.3、查看当前数据库

db

3.2.4、删除数据库

删除当前数据库库,默认为 test

3.3、集合操作

3.3.1、创建集合

name:要创建的集合名称
options:可选参数,指定有关内存大小及索引的选项

options 参数列表:

字段类型描述
capped布尔值如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数
autoIndexId布尔值如为 true,自动在 _id 字段创建索引,默认为false
size数值为固定集合指定一个最大值,以千字节计(KB)如果 capped 为 true,也需要指定该字段
max数值指定固定集合中包含文档的最大数量

在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段

不过在 MongoDB 中,你可以不用创建集合。当你插入一些文档时,MongoDB 会自动创建集合

3.3.2、查看所有集合

show collections
show tables

3.3.3、删除集合

3.4、文档操作

3.4.1、插入文档

MongoDB 使用 insert() 或 save() 方法向集合中插入文档,语法如下:

  • 第一次插入数据时,不需要预先创建一个集合“customer”,插入数据时会自动创建

  • 每次插入数据时如果没有显示的指定字段 “_id”,则会默认创建一个主键 “_id”。在关系数据库中主键大多数是数值类型,且是自动增长的序列。而 MongoDB 中的主键值类型则为 Objectld 类型,这样设计的好处是能更好的支持分布式存储

  • 在 MongoDB 中,每一个集合都必须有一个_id"字段,不管是自动生成的还是指定的,值都必须唯一,如果插入重复值将会抛出异常

单个插入

#将一条记录插入到collection表中,会自动添加_id字段,并分配_id字段的值
db.events.insert({"name":"demo record"}) #不推荐
db.events.insertOne({"name":"demo record"})

批量插入

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

3.4.2、查看文档

查看某个集合下全部文档

db.collection_name.find()
db.collection_name.find({})

条件查询

db.collection_name.find({条件})

#示例
#查询status字段为A或D的文档
db.inventory.find( { status: { $in: [ "A", "D" ] } } )

投影查询

  • 其中1表示显示该字段,0表示不显示
db.collection_name.find({条件},{字段:1})

#示例
# 查询文档中status=D的文档,只返回文档中status和size两个字段的值
db.inventory.find({ status: "D" },{status:1,size:1})
# 查询文档中status=D的文档,返回除了size字段的所有字段 
db.inventory.find({ status: "D" },{size:0})

3.4.3、查询选择器

插入测试数据

(1)查找全部
按照插入的顺序返回前 20 个文档,如果记录总数比 20 大,则我们可以通过命令it获取更多文档

(2)精确匹配选择器

# 返回包含键值对 id:9 的文档
db.customers.find({id:9})
# 精确匹配选择器,但查询条件是要返回同时匹配键值对 name:"xiaoming"且 age:101 的文档
> db.customers.find({name:"xiaoming",age:101})

(3)比较运算符

运算符解释
$lt表示的是小于
$lte表示的小于或等于
$gt表示的是大于
$gte表示的是大于或等于
$ne表示不等于;单独使用$ne,它也不会利用索引的优势,反而会进行全表扫描

使用示例:

db.customers.find({age:{$lt:102}})
db.customers.find({age:{$lte:102}})
db.customers.find({age:{$gt:109}})
db.customers.find({age:{$gte:109}})
db.customers.find({id:{$ne:1}})

(4)范围选择器

# 表示的是小于 120,大于或等于 119
db.customers.find({age:{$lt:120,$gte:119}})

(5)$in 和 $nin

# 表示返回 key 的值在某些 value 范围内
db.customers.find({id:{$in:[1,2]}}) 
# $nin 表示返回 key 的值不在某些 value 范围内,$nin 是一种比较低效的査询选择器,它会进行全表扫描,因此最好不要单独使用$nin 
db.customers.find({id:{$nin:[1,2]}})

(6)逻辑运算符

# $or 表示或运算的选择器,主要用于对两个不同 key 对应的文档进行连接
db.customers.find({$or:[{id:11},{age:119}]
# $and 表示与运算的选择器,对于两个不同的 key,要同时满足条件
db.customers.find({$and:[{id:11},{age:111}]})

(7)嵌套查询

3.4.4、修改文档

语法:

db.collection.update( <query>,  <update>,
	{upsert: <boolean>,multi: <boolean>,writeConcern: <document>})

示例:

# 这个操作将更改集合中与name: "apple"匹配的第一个文档,使用$set将其中的字段name设为"apple5s",使用$inc将字段price增加4000,其他字段保持不变。
db.goods.update({name: "apple"},{$set: {name: "appleSs"},$inc: {price:4000}}) 

# updateOne和updateMany操作
# 1.按条件更新数据,只更新查询排在第一位的数据
db.inventory.updateOne({ "status" : "D" },{ $set: { "item" : "journal"} },{ upsert: true });
# 2.更新满足条件的全部数据
db.inventory.updateMany({ "qty" : { $gt: 75 } },{ $set: { status: "A" } });

3.4.5、删除文档

# 删除集合下全部文档:
db.inventory.deleteMany({})
# 删除满足条件的全部文档:
db.inventory.deleteMany({ status : "A" })
# 删除一个文档:
db.inventory.deleteOne( { status: "D" } )

3.5、MongoDB 加载 CSV 文件

(1)下载工具包

yum -y install mongodb-org-tools-4.0.1

(2)加载文件

#无用户名和密码
mongoimport --headerline --type=csv --file=./train.csv -d events -c train
#有用户名和密码
mongoimport --headerline --type=csv --file=./train.csv -d events -c train --port 27017 -u "user_name" -p "password" --authenticationDatabase "admin"

4、MongoDB 整合 hive

4.1、导入 Jar 包

第一次整合 hive 和 MongoDB 需要导入相应的 Jar 包;需要请联系博主

mongo-hadoop-core-2.0.2.jar
mongo-hadoop-hive-2.0.2.jar
mongo-java-driver-3.6.0.jar

4.2、创建 hive 映射表

create table individuals(
id int,
name string,
age int,
work struct<title:string,hour:int>)
stored by "com.mongodb.hadoop.hive.MongoStorageHandler"
with serdeproperties
('mongo.columns.mapping"="{"id":"_id","work.title":"job.postition"}')
tblproperties
('mongo.uri'='[user_name:password@]mongodb://127.0.0.1:27017/test.persons');

4.3、插入数据验证

在 hive 中插入数据,然后到 MongoDB 中查看是否映射成功

hive > insert into individuals select 1,"zhangsan",20,named_struct('title','beijing','hour',10);
> db.persons.find()

成功结果如下:
在这里插入图片描述

5、MongoDB 认证

5.1、设置用户名和密码

进入 MongoDB 客户端,并进入 Admin 数据库;输入以下内容设置用户名和密码

db.createUser(
{
user:"kgc",
pwd:"123456",
roles:[{role:"userAdminAnyDatabase",db:"admin"},"readWriteAnyDatabase"]
}
)

5.2、修改配置文件

关闭 MongoDB 服务,修改配置文件后重启服务

vim /etc/mongod.conf
security:
  authorization: enabled

5.3、用户登录 MongoDB

6、Spark 操作 MongoDB

添加依赖项

	<properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <encoding>UTF-8</encoding>
        <scala.version>2.11.8</scala.version>
        <spark.version>2.2.0</spark.version>
        <hadoop.version>2.7.1</hadoop.version>
        <scala.compat.version>2.11</scala.compat.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>${scala.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>

        <dependency>
            <groupId>org.mongodb.spark</groupId>
            <artifactId>mongo-spark-connector_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <!--java打包插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!--scala打包插件-->
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <includes>
                                <include>**/*.scala</include>
                            </includes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!--将依赖打入jar包-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

6.1、Spark 读 MongoDB

object ConnTest extends App {
  //创建spark对象
  val spark=SparkSession.builder()
    .master("local[2]")
    .appName("connTest")
    .config("spark.mongodb.input.uri","mongodb://192.168.8.99:27017/events.train")
    .getOrCreate()

  //读写MongoDB数据
  val dfTrain=MongoSpark.load(spark)
  dfTrain.printSchema()
  dfTrain.show()
}

6.2、Spark 写入 MongoDB

需要添加用户名和密码的写入格式

object ConnTest extends App {
  //创建spark对象
  val spark=SparkSession.builder()
    .master("local[2]")
    .appName("connTest")
    .config("spark.mongodb.output.uri","mongodb://kgc:[email protected]:27017/admin")
    .config("spark.mongodb.output.database","events")
    .config("spark.mongodb.output.collection","test2")
    .getOrCreate()

  //写数据到MongoDB
  val value: RDD[Document] = spark.sparkContext.parallelize((1 to 10))
    .map(i => Document.parse(s"{test:$i}"))
  MongoSpark.save(value)
}