MongoDB 学习

 一、什么是NoSQL?

  NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。

  NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。

  NoSQL的优点/缺点:

    优点:高可扩展性、分布式计算、低成本、架构的灵活性,半结构化数据、没有复杂的关系

    缺点:没有标准化、有限的查询功能(到目前为止)、最终一致是不直观的程序

  NoSQL数据库分类:

类型 部分代表 特点
列存储

Hbase

Cassandra

Hypertable

顾名思义,是按列存储数据的。最大的特点是方便存储结构化和半结构化数据,方便做数据压缩,对针对某一列或者某几列的查询有非常大的IO优势。
文档存储

MongoDB

CouchDB

文档存储一般用类似json的格式存储,存储的内容是文档型的。这样也就有机会对某些字段建立索引,实现关系数据库的某些功能。
key-value存储

MemcacheDB

Redis

可以通过key快速查询到其value。一般来说,存储不管value的格式,照单全收。(Redis包含了其他功能)
图存储

Neo4J

FlockDB

图形关系的最佳存储。使用传统关系数据库来解决的话性能低下,而且设计使用不方便。
对象存储

db4o

Versant

通过类似面向对象语言的语法操作数据库,通过对象的方式存取数据
xml数据库

Berkeley DB XML

BaseX

 高效的存储XML数据,并支持XML的内部查询语法,比如XQuery,Xpath

二、什么是MongoDB?

  官网:https://www.mongodb.com/2

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

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

  MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

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

  

  1、MongoDB概念/与SQL区别

SQL术语/概念MongoDB术语/概念解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins   表连接,MongoDB不支持
primary key primary key 主键,MongoDB自动将_id字段设置为主键

  示例:

  

  2、MongoDB连接

  mongodb://[username:password@]host1[:port1] [,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

    mongodb:// 这是固定的格式,必须要指定。

    username:password@ 可选项,如果设置,在连接数据库服务器之后,驱动都会尝试登录这个数据库

    host1 必须的指定至少一个host, host1 是这个URI唯一要填写的。它指定了要连接服务器的地址。如果要连接复制集,请指定多个主机地址。

    portX 可选的指定端口,如果不填,默认为27017

    /database 如果指定username:password@,连接并验证登录指定数据库。若不指定,默认打开 test 数据库。

    ?options 是连接选项。如果不使用/database,则前面需要加上/。所有连接选项都是键值对name=value,键值对之间通过&或;(分号)隔开

  

    如:

      使用用户名fred,密码foobar登录localhost的baz数据库:mongodb://fred:foobar@localhost/baz

      连接 replica set 三台服务器 (端口 27017, 27018, 和27019):mongodb://localhost,localhost:27018,localhost:27019

    

  3、常用的命令:

    1、show dbs :显示所有数据库的列表

    2、use [db名称]:指定一个数据库、如果没有则会创建此数据库

    3、db:显示当前数据库对象或集合

    4、show collections:显示当前库下所有的集合

    5、db.dropshiyongDatabase():先使用use命令切换到要删除的库下,然后使用此命令删除当前库

    6、db.collection.drop():删除集合

    7、db.createCollection(name, options):创建集合,options可选参数(具体参考文档)。

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

    8、db.COLLECTION_NAME.insert(document) :向集合中插入文档(一条记录),如果集合mycol2不存在,会自动创建

      9、db.col.remove({'key1':'MongoDB 教程'}):删除

  4、MongoDB查询文档

    db.collection.find(query, projection)

      query :可选,使用查询操作符指定查询条件  

      projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)

      db.col.find().pretty(): 使用pretty方法,使结果易读

  

      1)MongoDB与RDBMS WHERE语句比较

操作格式范例RDBMS中的类似语句
等于 {<key>:<value>} db.col.find({"key1":"value1"}).pretty() where key1 = 'value1'
小于 {<key>:{$lt:<value>}} db.col.find({"key1":{$lt:50}}).pretty() where key1 < 50
小于或等于 {<key>:{$lte:<value>}} db.col.find({"key1":{$lte:50}}).pretty() where key1 <= 50
大于 {<key>:{$gt:<value>}} db.col.find({"key1":{$gt:50}}).pretty() where key1 > 50
大于或等于 {<key>:{$gte:<value>}} db.col.find({"key1":{$gte:50}}).pretty() where key1 >= 50
不等于 {<key>:{$ne:<value>}} db.col.find({"key1":{$ne:50}}).pretty() where key1 != 50

      2)AND 条件

       MongoDB 的 find() 方法可以传入多个键(key),每个键(key)以逗号隔开,即常规 SQL 的 AND 条件。语法格式如下:

        >db.col.find({key1:value1, key2:value2}).pretty()

      3)OR 条件

      OR 条件语句使用了关键字 $or,语法格式如下:

        >db.col.find(
           {
              $or: [
                 {key1: value1}, {key2:value2}
              ]
           }
        ).pretty()
      表示查询键为key1,值为value1或键为key2,值为value2的文档

      4)AND 和 OR 联合使用

        >db.col.find({"likes": {$gt:50}, $or: [{"by": "菜鸟教程"},{"title": "MongoDB 教程"}]}).pretty()

      5)排序 ,使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。

        >db.COLLECTION_NAME.find().sort({KEY:1})

      

  5、索引

    索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构

    1) 创建索引:createIndex()

        注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。

      >db.collection.createIndex(keys, options)

        key为要创建索引的字段,1表示按升序创建索引,-1表示按降序创建索引。如:db.col.createIndex({"title":1,"description":-1}),表示创建title和description两个字段的索引,一个升序,一个降序

        options 选项参考文档

  6、与Java整合

    1)引入依赖

<dependencies>
    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo-java-driver</artifactId>
        <version>3.5.0</version>
    </dependency>
</dependencies>

    2)建立连接

MongoClientURI connectionString = new MongoClientURI("mongodb://localhost:27017,localhost:27018,localhost:27019");
// MongoClient实例表示与数据库的连接池。即使有多个线程,您也只需要一个MongoClient类的实例。
// 所以我们可以在给定的数据库集群创建一个MongoClient实例,并在整个应用程序中使用它
MongoClient mongoClient = new MongoClient(connectionString);
// 连接具体数据库
MongoDatabase database = mongoClient.getDatabase("mydb");

    3)增删改查操作

// 获取某个集合
MongoCollection<Document> collection = database.getCollection("test");

// 创建一条文档(JSON对象字符串)
Document doc = new Document("name", "MongoDB")
               .append("type", "database")
               .append("count", 1)
               .append("info", new Document("x", 203).append("y", 102));

// 插入文档
collection.insertOne(doc);

// 批量插入
List<Document> documents = new ArrayList<Document>();
collection.insertMany(documents);

// 获取集合下文档数量
collection.count()

// 查询集合中的第一条文档
Document myDoc = collection.find().first();

// 查询集合中的所有文档
MongoCursor<Document> cursor = collection.find().iterator();
try {
    while (cursor.hasNext()) {
        System.out.println(cursor.next().toJson());
    }
} finally {
    cursor.close();
}

//  使用filter查询符合条件的记录,如查询field为age,值为26的文档记录
Document myDoc = collection.find(eq("age", 26)).first();

// 查询符合条件(50<i<100)的多条文档,并遍历
// now use a range query to get a larger subset
Block<Document> printBlock = new Block<Document>() {
     @Override
     public void apply(final Document document) {
         System.out.println(document.toJson());
     }
};
collection.find(and(gt("i", 50), lte("i", 100))).forEach(printBlock);

// 对i字段进行降序 
Document myDoc = collection.find(exists("i")).sort(descending("i")).first();

// 查询到的文档排除掉 _id 字段    
Document myDoc = collection.find().projection(excludeId()).first();

// 更新符合过滤器的最多一个文档,使用updateOne。如更新i字段等于10的第一条符合记录的文档,并将i更新为110
collection.updateOne(eq("i", 10), new Document("$set", new Document("i", 110)));

// 更新符合过滤器的所有文档,使用updateMany。如更新字段i为10的所有所有文档,返回的UpdateResult 包含更新的文档数
UpdateResult updateResult = collection.updateMany(lt("i", 100),
          new Document("$inc", new Document("i", 100)));

// 删除文档
collection.deleteOne(eq("i", 110));
DeleteResult deleteResult = collection.deleteMany(gte("i", 100));
View Code

 附录:

  Mongo连接工具类:

import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoDatabase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.util.Properties;

/**
 * @author yangyongjie
 * @date 2021/1/25
 * @desc
 */
public enum MongoUtil {

    /**
     * 定义一个枚举元素,代表此类的一个实例
     */
    INSTANCE;

    private static final Logger LOGGER = LoggerFactory.getLogger(MongoUtil.class);

    private MongoClient mongoClient;

    /**
     * 重写枚举类的构造方法,枚举类经编译后会在将其放在静态代码块中,在类加载的初始化阶段被调用
     */
    private MongoUtil() {
        Properties properties = null;
        try {
            properties = PropertiesLoaderUtils.loadAllProperties("application.properties");
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (properties != null) {
            MongoClientURI connectionString = new MongoClientURI(properties.getProperty("mongo.url"));
            // MongoClient实例表示与数据库的连接池。即使有多个线程,您也只需要一个MongoClient类的实例。
            // 所以我们可以在给定的数据库集群创建一个MongoClient实例,并在整个应用程序中使用它
            this.mongoClient = new MongoClient(connectionString);
        }
    }

    /*private static MongoClient mongoClient;

    static {
        Properties properties = new Properties();
        try {
            InputStream is = ClassLoader.getSystemResourceAsStream("application.properties");
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (properties != null) {
            MongoClientURI connectionString = new MongoClientURI(properties.getProperty("mongo.url"));
            // MongoClient实例表示与数据库的连接池。即使有多个线程,您也只需要一个MongoClient类的实例。
            // 所以我们可以在给定的数据库集群创建一个MongoClient实例,并在整个应用程序中使用它
            mongoClient = new MongoClient(connectionString);
        }
    }*/
    
    public MongoDatabase getDB(String dbName) {
        if (dbName != null && !"".equals(dbName)) {
            MongoDatabase database = mongoClient.getDatabase(dbName);
            return database;
        }
        return null;
    }

}
View Code

  用法:MongoUtil.INSTANCE.getMiShopDB("db") 

END.

  
原文地址:https://www.cnblogs.com/yangyongjie/p/14200740.html