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());
}
}
}

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. springboot部分常用注解

    目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...

  2. C#调用原生C++ COM对象(在C++中实现C#的接口)

    为了跨平台在.net core中使用COM,不能使用Windows下的COM注册机制,但是可以直接把IUnknown指针传给C#,转换为指针,再转换为C#的接口(interface). 做了这方面的研 ...

  3. Apache Linux下Apache安装步骤

    Apache简介         Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广 ...

  4. Mysql----修改MySQL5.7的root的密码

    在开始服务的情况之下 进入mysql  更改密码:update mysql.user set authentication_string=password('新的密码') where  user='r ...

  5. Linux唤醒抢占----Linux进程的管理与调度(二十三)

    1. 唤醒抢占 当在try_to_wake_up/wake_up_process和wake_up_new_task中唤醒进程时, 内核使用全局check_preempt_curr看看是否进程可以抢占当 ...

  6. February 22nd, 2018 Week 8th Thursday

    Confine yourself to the present. 着眼当下. The morning wind spreads its fresh smell, we should get up an ...

  7. linux上部署SpringBoot项目及遇到的问题

    打开sftp步骤, 在显示的已连接的窗口上右键, 选择connect SFTP Session就可以打开文件上传的窗口 从windows上传文件到linux, 首先linux需要先切换到想要保存文件的 ...

  8. C语言的main函数到底该怎么写

    公众号[编程珠玑]:专注但不限于分享计算机编程基础,Linux,C语言,C++,Python,数据库等编程相关[原创]技术文章,号内包含大量经典电子书和视频学习资源.欢迎一起交流学习,一起修炼计算机“ ...

  9. 推酷文章中编写js组件系列文章整理

    一步一步实现JS拖拽插件 http://www.tuicool.com/articles/RBbmMjY JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享 http://ww ...

  10. React项目中那些奇怪的写法

    1.在一个React组件里看到一个奇怪的写法: const {matchs} = this.props.matchs; 原来,是解构赋值,虽然听说过,但是看起来有点奇怪 下面做个实验: <scr ...