Author:SimpleWu

聚合

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

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

$group

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

  1. //根据员工gender来分组并且统计数量
  2. 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在读取数据时必须扫描集合中的每个文档,并选取那些符合查询条件的记录。

创建索引语法:

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

索引的常见操作

  1. //查看集合索引
  2. db.emp.getIndexes()
  3. //查看集合索引大小
  4. db.emp.totalIndexSize()
  5. //删除集合所有索引
  6. db.emp.dropIndexes()
  7. //删除集合指定索引
  8. db.emp.dropIndex("索引名称")

索引的种类

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

id索引

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

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

单键索引

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

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

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

多键索引

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

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

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

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

复合索引

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

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

索引的命名

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

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

唯一索引

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

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

过期索引

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

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

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

过期索引的一些限制:

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

全文索引

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

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

使用全文索引

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

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

全文索引的相似度

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

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

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

全文索引的限制

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

索引的注意事项

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

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

explain执行计划

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

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

  1. 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/

  1. <dependency>
  2. <groupId>org.mongodb</groupId>
  3. <artifactId>mongodb-driver</artifactId>
  4. <version>3.9.0</version>
  5. </dependency>

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

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

我们可以使用 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 方法删除。

个人测试结果,基本操作:

  1. package com.simple.nosql.mongodb;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import org.bson.Document;
  7. import org.junit.Before;
  8. import org.junit.Test;
  9. import com.mongodb.MongoClient;
  10. import com.mongodb.client.FindIterable;
  11. import com.mongodb.client.MongoCollection;
  12. import com.mongodb.client.MongoCursor;
  13. import com.mongodb.client.MongoDatabase;
  14. import com.mongodb.client.result.DeleteResult;
  15. import com.mongodb.client.result.UpdateResult;
  16. /**
  17. * MangoDB基本操作
  18. * @author SimpleWu
  19. *
  20. */
  21. public class Test1 {
  22. private MongoClient mongoClient = null;
  23. /**
  24. * 获取MongoDB客户端连接
  25. *
  26. * @return
  27. */
  28. public MongoClient getMongoClient() {
  29. this.mongoClient = new MongoClient("localhost", 27017);
  30. return this.mongoClient;
  31. }
  32. private MongoDatabase mongoDatabase = null;
  33. /**
  34. * 连接数据库,你需要指定数据库名称,如果指定的数据库不存在,mongo会自动创建数据库。
  35. */
  36. public MongoDatabase createConnection() {
  37. getMongoClient();// 获取客户端连接
  38. // 连接到数据库
  39. mongoDatabase = mongoClient.getDatabase("students");
  40. System.out.println("Connect to database successfully");
  41. return this.mongoDatabase;
  42. }
  43. @Before
  44. public void before() {
  45. createConnection();
  46. }
  47. /**
  48. * 我们可以使用 com.mongodb.client.MongoDatabase 类中的createCollection()来创建集合
  49. */
  50. @Test
  51. public void createCollection() {
  52. // 创建集合
  53. mongoDatabase.createCollection("employee");
  54. System.out.println("集合创建成功");
  55. }
  56. /**
  57. * 获取集合
  58. */
  59. public MongoCollection<Document> getCollection() {
  60. // 获取指定名称集合
  61. MongoCollection<Document> collection = mongoDatabase.getCollection("employee");
  62. System.out.println("集合获取成功");
  63. return collection;
  64. }
  65. /**
  66. * 插入文档
  67. */
  68. @Test
  69. public void testInsert() {
  70. // 获取集合
  71. MongoCollection<Document> collection = getCollection();
  72. Map<String, Object> map = new HashMap<>();
  73. map.put("_id", 1);
  74. map.put("name", "AA");
  75. map.put("email", "AA@gmail.com");
  76. map.put("info", "my name is AA");
  77. Document document = new Document(map);
  78. collection.insertOne(document);
  79. // 插入多个文档
  80. Document document1 = new Document();
  81. document1.append("_id", 2);
  82. document1.append("name", "BB");
  83. document1.append("email", "BB@gmail.com");
  84. document1.append("info", "my name is BB");
  85. Document document2 = new Document();
  86. document2.append("_id", 3);
  87. document2.append("name", "CC");
  88. document2.append("email", "CC@gmail.com");
  89. document2.append("info", "my name is CC");
  90. List<Document> list = Arrays.asList(document1, document2);
  91. collection.insertMany(list);
  92. System.out.println("插入文档成功");
  93. }
  94. /**
  95. * 检索文档
  96. */
  97. @Test
  98. public void testFind() {
  99. // 获取集合
  100. MongoCollection<Document> collection = getCollection();
  101. // 检索所有文档
  102. FindIterable<Document> iterable = collection.find();
  103. //获取结果集
  104. MongoCursor<Document> cursor = iterable.iterator();
  105. while (cursor.hasNext()) {
  106. System.out.println(cursor.next());
  107. }
  108. // 获取name=AA的文档
  109. /*
  110. * Document document = new Document(); document.append("name", "AA");
  111. * FindIterable<Document> iterable = collection.find(document);
  112. * select(iterable);
  113. */
  114. }
  115. /**
  116. * 更新文档
  117. */
  118. @Test
  119. public void update() {
  120. // 获取集合
  121. MongoCollection<Document> collection = getCollection();
  122. //创建需要更新的条件
  123. Document document = new Document("name", "AA");
  124. //创建需要更新的内容
  125. Document upd = new Document("name", "AA-AA");
  126. //更新文档
  127. Document document1 = new Document("$set", upd);
  128. UpdateResult result = collection.updateOne(document, document1);
  129. System.out.println("更新成功");
  130. }
  131. /**
  132. * 指定条件查询
  133. */
  134. @Test
  135. public void eqLtGt(){
  136. MongoCollection<Document> collection = getCollection();
  137. //创建条件
  138. Document check = new Document("$eq", 1);
  139. //指定判断列
  140. Document document1 = new Document("_id",check);
  141. FindIterable<Document> iterable = collection.find(document1);
  142. select(iterable);
  143. }
  144. /**
  145. * 删除文档
  146. */
  147. @Test
  148. public void delete() {
  149. // 获取集合
  150. MongoCollection<Document> collection = getCollection();
  151. Document document = new Document("name", "BB");
  152. DeleteResult result = collection.deleteOne(document);
  153. System.out.println("删除数量 : " + result.getDeletedCount());
  154. }
  155. /**
  156. * 分页
  157. */
  158. @Test
  159. public void testPage(){
  160. getMongoClient();// 获取客户端连接
  161. // 连接到数据库
  162. mongoDatabase = mongoClient.getDatabase("students");
  163. // 获取集合总记录数
  164. Long count = mongoDatabase.getCollection("employee").count();
  165. MongoCollection<Document> collection = mongoDatabase.getCollection("employee");
  166. int pageSize = 2;//当前页
  167. int pageCount = 10;//每页文档数
  168. //开始页数,每页数量。取得结果值
  169. FindIterable<Document> iterable = collection.find().skip( (pageSize - 1) *pageCount).limit(pageCount);
  170. select(iterable);
  171. }
  172. public void select(FindIterable<Document> iterable) {
  173. MongoCursor<Document> cursor = iterable.iterator();
  174. while (cursor.hasNext()) {
  175. System.out.println(cursor.next());
  176. }
  177. }
  178. }

MangoDB高级应用的更多相关文章

  1. springboot整合Mangodb实现crud,高级查询,分页,排序,简单聚合

    //linux安装mangodb教程:https://www.cnblogs.com/yangxiaohui227/p/11347832.html 1.引入maven 依赖 <dependenc ...

  2. MySQL高级知识- MySQL的架构介绍

    [TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ...

  3. PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)

    100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...

  4. 马哥linux运维初级+中级+高级 视频教程 教学视频 全套下载(近50G)

    马哥linux运维初级+中级+高级 视频教程 教学视频 全套下载(近50G)目录详情:18_02_ssl协议.openssl及创建私有CA18_03_OpenSSH服务及其相关应用09_01_磁盘及文 ...

  5. JS高级前端开发群加群说明及如何晋级

    JS高级前端开发群加群说明 一.文章背景: 二. 高级群: 三. 加入方式: 四. 说明:   一.文章背景: 去年年初建了几个群,在不经意间火了,一直排在“前端开发”关键字搜索结果第一名.当然取得这 ...

  6. C#高级知识点&(ABP框架理论学习高级篇)——白金版

    前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...

  7. Visual Studio 宏的高级用法

    因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS. 在上一篇中,我已经介绍了如何编 ...

  8. [译]基于GPU的体渲染高级技术之raycasting算法

    [译]基于GPU的体渲染高级技术之raycasting算法 PS:我决定翻译一下<Advanced Illumination Techniques for GPU-Based Volume Ra ...

  9. 高薪诚聘熟悉ABP框架的.NET高级开发工程师(2016年7月28日重发)

    招聘单位是ABP架构设计交流群(134710707)群主阳铭所在的公司-上海运图贸易有限公司 招聘岗位:.NET高级开发工程师工作地点:上海-普陀区 [公司情况]上海运图贸易有限公司,是由易迅网的创始 ...

随机推荐

  1. Java 时间总结

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/80613024 本文出自[赵彦军的博客] 时区 整个地球分为二十四时区,每个时区都有 ...

  2. Android/IOS手机使用Fiddler抓包

    对于Android和IOS开发及测试的同事来说抓包是一个很重要的事,有利于排查问题所在,快速定位问题.但长期以来一直没有一款可以快速抓包的工具,直到有了Fiddler2. 使用步骤: 1.  Fidd ...

  3. spring4笔记----使用装配注入合作者Bean的三种方式

    no :不自动装配 byName :id(name)与setter方法去set前缀,并小写首字母后同名的Bean完成注入,如有多个匹配则抛异常 byType :spring容器找全部bean,如果找到 ...

  4. C#-运算符(四)

    算术运算符 +:两个操作数相加,例:2+3得5 -:第一个操作数减去第二个操作数 例:5-3得2 *:两个操作数相乘,例:2*3得6 /:分子除以分母,例:5/2得2 %:取模运算符,整除后的余数,例 ...

  5. ASP.NET MVC从视图传参到控制器的几种形式

    1. 传递数组 $(function () { var value = ["C#", "JAVA", "PHP"]; $("inp ...

  6. sql视图显示数据不对应

    出现这样的原因是修改了表的结构,没有重新编译视图,这种情况出现的几率很少,并不是没有. 解决方法:重新编译一下该视图. 视图是一个虚表,是从一个或几个基本表(或视图)中导出的表,在系统的数据字典中仅存 ...

  7. Django之--通过MVC架构的html模板展示Hello World!

    上一篇:Django之--网页展示Hello World! 初步说明了如何使用Django来显示hello world,本文略微进阶下使用html模板来展示hello world~ 首先在mysite ...

  8. python3爬虫抓取智联招聘职位信息代码

    上代码,有问题欢迎留言指出. # -*- coding: utf-8 -*- """ Created on Tue Aug 7 20:41:09 2018 @author ...

  9. Cs231n课堂内容记录-Lecture1 导论

    Lecture 1 视频网址:https://www.bilibili.com/video/av17204303/?p=2 https://zhuanlan.zhihu.com/p/21930884? ...

  10. [Hive_add_6] Hive 实现 Word Count

    0. 说明 Hive 通过 explode()函数 和 split()函数 实现 WordConut 1. Hive 实现 Word Count 方式一 1.1 思路 将每一行文本变为 Array 数 ...