• MongoDB基础应用


    Author:SimpleWu

    聚合

    聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。

    //统计员工总数
    db.emp.aggregate([{$count:"countName"}])
    //或者
    db.emp.find().count()
    

    $group

    使用$group是对筛选的数据进行分组。类似于mysql中的group by关键字。

    //根据员工gender来分组并且统计数量
    db.emp.aggregate([{$group : {_id : "$gender", count: {$sum : 1}}}])
    

    说明:

    • 这里_id是表示分组的字段,名字是固定的。
    • count表示聚合生成列的名称。
    • $sum表示聚合函数。
    • 1统计的值,其他聚合函数也可以是字段。

    聚合表达式

    表达式 描述 实例
    $sum 计算总和。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}])
    $avg 计算平均值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}])
    $min 获取集合中所有文档对应值得最小值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}])
    $max 获取集合中所有文档对应值得最大值。 db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}])
    $push 在结果文档中插入值到一个数组中。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}])
    $addToSet 在结果文档中插入值到一个数组中,但不创建副本。 db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}])
    $first 根据资源文档的排序获取第一个文档数据。 db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}])
    $last 根据资源文档的排序获取最后一个文档数据 db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}])

    这些聚合函数基本上与mysql,oracle中效果是一致的。

    索引

    所以这东西学习过数据库的都知道是不可缺少的,当然我们的MangoDB也是有的。

    索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文档,并选取那些符合查询条件的记录。

    创建索引语法:

    db.collection.createIndex(keys, options)
    /*
    key:你要创建的索引字段,1 为指定按升序创建索引,如果你想按降序来创建索引指定为 -1 即可。如果多个字段使用,隔开
    */
    db.emp.createIndex({"name":1})                    #创建单列索引
    db.emp.createIndex({"name":1,"age":-1})      #创建多列索引。
    

    索引的常见操作

    //查看集合索引
    db.emp.getIndexes()
    //查看集合索引大小
    db.emp.totalIndexSize()
    //删除集合所有索引
    db.emp.dropIndexes()
    //删除集合指定索引
    db.emp.dropIndex("索引名称")
    
    

    索引的种类

    在mysql里面索引有许多种类当然我们的MongoDB中也有很多种类:id索引、单键索引、多键索引、复合索引、过期索引、全文索引。

    id索引

    ID索引也称为主键索引,是我们创建一个集合时,自动创建的索引。

    集合的默认排序是按照id来进行排序的。在mongodb中id是根据ObjectId()来生成的,这个顺序是以时间撮来进行生成。

    单键索引

    单键索引是最普通的索引。

    和id索引不同,单键索引不会自动创建,需要我们手动创建。

    db.col.createIndex({"name":1})//创建单列索引,对name列创建索引
    

    多键索引

    多键索引和单键索引创建形式相同,区别在于字段的值。

    单键索引:值是一个单一的值,例如:字符串,数字或者日期。

    多键索引:值有多个记录,例如:数组。

    db.emp.createIndex({"name":1,"age":-1})//创建多列索引,对name和age创建索引
    

    复合索引

    当我们的查询条件不只一个时,就需要建立符合索引。符合索引是在多个列上同时创建索引。

    db.col.createIndex({"name":1,"age":-1})  //创建复合索引。
    

    索引的命名

    默认情况下,索引的命名是列+1或者-1,这种方式不是很方面记忆,而且删除是也不太方面。这时候我们就需要为索引创建一个名称。

    //创建索引并命名为ix_name。
    db.students.createIndex({name:-1},{name:"ix_name"})
    

    唯一索引

    我们可以为索引添加一个唯一性,从而保存该列的数据不允许重复。

    //创建索引并命名为ix_name。
    db.students.createIndex({name:-1},{name:"ix_name",unique:true})
    

    过期索引

    过期索引:就是在一段时间后会自动过期的索引。在索引过期后,相应的数据也会被删除。

    适合存储一些希望一段时间后会失效的数据,比如用户登录信息,存储的日志等。

    db.collections.createIndex({time:1},{expireAfterSeconds:10})
    

    过期索引的一些限制:

    • 过期索引的值必须是指定的时间类型,必须使用ISODate或者ISODate数组,不能使用时间撮,否则不会被自动删除。
    • 如果指定的是ISODate数组,则按照最小时间删除。
    • 过期索引不能是复合索引。
    • 删除时间是有一定的误差,由于删除过程是由后台程序每60秒跑一次,而且删除数据也需要一定的时间。所以存在误差。

    全文索引

    当要对一篇文章中的文本内容进行搜索的时候,这个时候可以考虑全文索引。全文索引可以加快检索内容关键字的效率。全文索引只能对字符串或者字符串数组有效。

    //创建全文索引
    db.students.createIndex({name:"text",info:"text"})
    

    使用全文索引

    创建好全文索引后,我们就可以来使用全文索引,使用全文索引需要使用$text和$search两个运算符。

    //查找全文索引中包含了zhangsan的文档。
    db.students.find({$text:{$search:"zhangsan"}})
    
    //查找全文索引中包含了zhangsan或者zhangsanfeng的文档。
    db.students.find({$text:{$search:"zhangsan zhangsanfeng"}})
    
    //查找全文索引中包含了zhangsan,但不包含zhangsanfeng的文档。
    db.students.find({$text:{$search:"zhangsan -zhangsanfeng"}})
    
    //查找全文索引中包含了zhangsan和zhangsanfeng的文档。
    db.students.find({$text:{$search:""zhangsan" "zhangsanfeng""}})
    

    全文索引的相似度

    我们在百度中搜索时,经常会看到和我们关键字匹配度越高的,排行就越靠前。在mongodb中,我们还可以返回查询结果的相似度,与sort一起使用效果会更好。

    使用方式:在find后面跟上{score:{$meta:"textScore"}}

    db.students.find({$text:{$search:"zhangsan"}},{score:{$meta:"textScore"}})
    .sort({score:{$meta:"textScore"}})
    

    全文索引的限制

    • 每次查询只能指定一个text。
    • text操作符不能出现在$nor查询中。
    • 查询中如果包含了text则hint将不再起作用。
    • mongodb的全文索引对中文支持不是很好。

    索引的注意事项

    索引像一把双刃剑,用得好可以提高查询效率,如果用不好可能会导致性能的降低。

    • $where和$exists完全不能走索引
    • ne取反操作效率很低
    • $not、$nin$or、$in

    explain执行计划

    索引的性能如何,我们可以通过explain执行计划来进行分析,从而使索引的性能达到最优。

    explain的使用方式非常简单,我们只需要在执行的find()命令后添加一个explain()方法即可。

    db.students.find().explain();
    

    文档之间的关系

    很多时候数据库中的数据不是单独存在的,数据和数据之间会有一些相互之间的联系。我们mongodb可以配置这种数据之间的关系。

    文档之间的关系

    • 一对一(one to one)
    • 一对多(one to many)
    • 多对一(many to one)
    • 多对多(many to many)

    每种关系又可以有两种方式来实现。

    嵌入式:嵌套在一个document文档中。

    引用式:通过外键引用的方式来实现。

    Java操作MongoDB

    下载MongoDB驱动http://mongodb.github.io/mongo-java-driver/

    <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongodb-driver</artifactId>
            <version>3.9.0</version>
    </dependency>
    

    连接数据库,你需要指定数据库名称,如果指定的数据库不存在,mongo会自动创建数据库。

    public static void main( String args[] ){
          try{   
             // 连接到 mongodb 服务
             MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
           
             // 连接到数据库
             MongoDatabase mongoDatabase = mongoClient.getDatabase("students");  
             System.out.println("Connect to database successfully");
            
          }catch(Exception e){
             System.err.println( e.getClass().getName() + ": " + e.getMessage() );
         }
       }
    

    我们可以使用 com.mongodb.client.MongoDatabase 类中的createCollection()来创建集合

    我们可以使用com.mongodb.client.MongoCollection类的 insertMany() 方法来插入一个文档。

    我们可以使用 com.mongodb.client.MongoCollection 类中的 find() 方法来获取集合中的所有文档。

    你可以使用 com.mongodb.client.MongoCollection 类中的 updateMany() 方法来更新集合中的文档。

    要删除集合中的第一个文档,首先你需要使用com.mongodb.DBCollection类中的 findOne()方法来获取第一个文档,然后使用remove 方法删除。
    个人测试结果,基本操作:

    package com.simple.nosql.mongodb;
    
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.bson.Document;
    import org.junit.Before;
    import org.junit.Test;
    
    import com.mongodb.MongoClient;
    import com.mongodb.client.FindIterable;
    import com.mongodb.client.MongoCollection;
    import com.mongodb.client.MongoCursor;
    import com.mongodb.client.MongoDatabase;
    import com.mongodb.client.result.DeleteResult;
    import com.mongodb.client.result.UpdateResult;
    
    /**
     * MangoDB基本操作
     * @author SimpleWu
     *
     */
    public class Test1 {
    
    	private MongoClient mongoClient = null;
    
    	/**
    	 * 获取MongoDB客户端连接
    	 * 
    	 * @return
    	 */
    	public MongoClient getMongoClient() {
    		this.mongoClient = new MongoClient("localhost", 27017);
    		return this.mongoClient;
    	}
    
    	private MongoDatabase mongoDatabase = null;
    
    	/**
    	 * 连接数据库,你需要指定数据库名称,如果指定的数据库不存在,mongo会自动创建数据库。
    	 */
    	public MongoDatabase createConnection() {
    		getMongoClient();// 获取客户端连接
    		// 连接到数据库
    		mongoDatabase = mongoClient.getDatabase("students");
    		System.out.println("Connect to database successfully");
    		return this.mongoDatabase;
    
    	}
    
    	@Before
    	public void before() {
    		createConnection();
    	}
    
    	/**
    	 * 我们可以使用 com.mongodb.client.MongoDatabase 类中的createCollection()来创建集合
    	 */
    	@Test
    	public void createCollection() {
    		// 创建集合
    		mongoDatabase.createCollection("employee");
    		System.out.println("集合创建成功");
    	}
    
    	/**
    	 * 获取集合
    	 */
    	public MongoCollection<Document> getCollection() {
    		// 获取指定名称集合
    		MongoCollection<Document> collection = mongoDatabase.getCollection("employee");
    		System.out.println("集合获取成功");
    		return collection;
    	}
    
    	/**
    	 * 插入文档
    	 */
    	@Test
    	public void testInsert() {
    		// 获取集合
    		MongoCollection<Document> collection = getCollection();
    		Map<String, Object> map = new HashMap<>();
    		map.put("_id", 1);
    		map.put("name", "AA");
    		map.put("email", "AA@gmail.com");
    		map.put("info", "my name is AA");
    		Document document = new Document(map);
    		collection.insertOne(document);
    
    		// 插入多个文档
    		Document document1 = new Document();
    		document1.append("_id", 2);
    		document1.append("name", "BB");
    		document1.append("email", "BB@gmail.com");
    		document1.append("info", "my name is BB");
    		Document document2 = new Document();
    		document2.append("_id", 3);
    		document2.append("name", "CC");
    		document2.append("email", "CC@gmail.com");
    		document2.append("info", "my name is CC");
    		List<Document> list = Arrays.asList(document1, document2);
    		collection.insertMany(list);
    		System.out.println("插入文档成功");
    	}
    
    	/**
    	 * 检索文档
    	 */
    	@Test
    	public void testFind() {
    		// 获取集合
    		MongoCollection<Document> collection = getCollection();
    		
    		// 检索所有文档
    		FindIterable<Document> iterable = collection.find();
    		
    		//获取结果集
    		MongoCursor<Document> cursor = iterable.iterator();
    		while (cursor.hasNext()) {
    			System.out.println(cursor.next());
    		}
    
    		// 获取name=AA的文档
    		/*
    		 * Document document = new Document(); document.append("name", "AA");
    		 * FindIterable<Document> iterable = collection.find(document);
    		 * select(iterable);
    		 */
    	}
    
    	/**
    	 * 更新文档
    	 */
    	@Test
    	public void update() {
    		// 获取集合
    		MongoCollection<Document> collection = getCollection();
    		//创建需要更新的条件
    		Document document = new Document("name", "AA");
    		//创建需要更新的内容
    		Document upd = new Document("name", "AA-AA");
    		//更新文档
    		Document document1 = new Document("$set", upd);
    		UpdateResult result = collection.updateOne(document, document1);
    		System.out.println("更新成功");
    	}
    	
    	/**
    	 * 指定条件查询
    	 */
    	@Test
    	public void eqLtGt(){
    		MongoCollection<Document> collection = getCollection();
    		
    		//创建条件
    		Document check = new Document("$eq", 1);
    		
    		//指定判断列
    		Document document1 = new Document("_id",check);
    		
    		FindIterable<Document> iterable = collection.find(document1);
    		
    		select(iterable);
    	}
    
    	/**
    	 * 删除文档
    	 */
    	@Test
    	public void delete() {
    		// 获取集合
    		MongoCollection<Document> collection = getCollection();
    		
    		Document document = new Document("name", "BB");
    		
    		DeleteResult result = collection.deleteOne(document);
    		
    		System.out.println("删除数量 : " + result.getDeletedCount());
    	}
    
            /**
    	 * 分页
    	 */
    	@Test
    	public void testPage(){
    		getMongoClient();// 获取客户端连接
    		// 连接到数据库
    		mongoDatabase = mongoClient.getDatabase("students");
    		// 获取集合总记录数
    		Long count = mongoDatabase.getCollection("employee").count();
    		
    		MongoCollection<Document> collection = mongoDatabase.getCollection("employee");
    		
    		int pageSize = 2;//当前页
    		int pageCount = 10;//每页文档数
    		//开始页数,每页数量。取得结果值
    		FindIterable<Document> iterable  = collection.find().skip( (pageSize - 1) *pageCount).limit(pageCount);
    		select(iterable);
    	}
    
    	public void select(FindIterable<Document> iterable) {
    		MongoCursor<Document> cursor = iterable.iterator();
    		while (cursor.hasNext()) {
    			System.out.println(cursor.next());
    		}
    	}
    }
    
  • 相关阅读:
    设计模式-观察者模式
    获取ubuntu中软件包的有用地址
    vim 简单命令
    adb logcat 日志过滤
    shell编程——
    shell编程——参数传递
    Chromecast
    linux 广播
    【转】Git命令解说
    linux 多播
  • 原文地址:https://www.cnblogs.com/SimpleWu/p/10012219.html
Copyright © 2020-2023  润新知