MangoDB高级应用
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高级应用的更多相关文章
- springboot整合Mangodb实现crud,高级查询,分页,排序,简单聚合
//linux安装mangodb教程:https://www.cnblogs.com/yangxiaohui227/p/11347832.html 1.引入maven 依赖 <dependenc ...
- MySQL高级知识- MySQL的架构介绍
[TOC] 1.MySQL 简介 概述 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司. MySQL是一种关联数据库管理系统,将数据保存在不同的表中,而 ...
- PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)
100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...
- 马哥linux运维初级+中级+高级 视频教程 教学视频 全套下载(近50G)
马哥linux运维初级+中级+高级 视频教程 教学视频 全套下载(近50G)目录详情:18_02_ssl协议.openssl及创建私有CA18_03_OpenSSH服务及其相关应用09_01_磁盘及文 ...
- JS高级前端开发群加群说明及如何晋级
JS高级前端开发群加群说明 一.文章背景: 二. 高级群: 三. 加入方式: 四. 说明: 一.文章背景: 去年年初建了几个群,在不经意间火了,一直排在“前端开发”关键字搜索结果第一名.当然取得这 ...
- C#高级知识点&(ABP框架理论学习高级篇)——白金版
前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...
- Visual Studio 宏的高级用法
因为自 Visual Studio 2012 开始,微软已经取消了对宏的支持,所以本篇文章所述内容只适用于 Visual Studio 2010 或更早期版本的 VS. 在上一篇中,我已经介绍了如何编 ...
- [译]基于GPU的体渲染高级技术之raycasting算法
[译]基于GPU的体渲染高级技术之raycasting算法 PS:我决定翻译一下<Advanced Illumination Techniques for GPU-Based Volume Ra ...
- 高薪诚聘熟悉ABP框架的.NET高级开发工程师(2016年7月28日重发)
招聘单位是ABP架构设计交流群(134710707)群主阳铭所在的公司-上海运图贸易有限公司 招聘岗位:.NET高级开发工程师工作地点:上海-普陀区 [公司情况]上海运图贸易有限公司,是由易迅网的创始 ...
随机推荐
- springboot部分常用注解
目录:[持续更新.....] spring 部分常用注解 spring boot 学习之路1(简单入门) spring boot 学习之路2(注解介绍) spring boot 学习之路3( 集成my ...
- C#调用原生C++ COM对象(在C++中实现C#的接口)
为了跨平台在.net core中使用COM,不能使用Windows下的COM注册机制,但是可以直接把IUnknown指针传给C#,转换为指针,再转换为C#的接口(interface). 做了这方面的研 ...
- Apache Linux下Apache安装步骤
Apache简介 Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行,由于其多平台和安全性被广 ...
- Mysql----修改MySQL5.7的root的密码
在开始服务的情况之下 进入mysql 更改密码:update mysql.user set authentication_string=password('新的密码') where user='r ...
- Linux唤醒抢占----Linux进程的管理与调度(二十三)
1. 唤醒抢占 当在try_to_wake_up/wake_up_process和wake_up_new_task中唤醒进程时, 内核使用全局check_preempt_curr看看是否进程可以抢占当 ...
- February 22nd, 2018 Week 8th Thursday
Confine yourself to the present. 着眼当下. The morning wind spreads its fresh smell, we should get up an ...
- linux上部署SpringBoot项目及遇到的问题
打开sftp步骤, 在显示的已连接的窗口上右键, 选择connect SFTP Session就可以打开文件上传的窗口 从windows上传文件到linux, 首先linux需要先切换到想要保存文件的 ...
- C语言的main函数到底该怎么写
公众号[编程珠玑]:专注但不限于分享计算机编程基础,Linux,C语言,C++,Python,数据库等编程相关[原创]技术文章,号内包含大量经典电子书和视频学习资源.欢迎一起交流学习,一起修炼计算机“ ...
- 推酷文章中编写js组件系列文章整理
一步一步实现JS拖拽插件 http://www.tuicool.com/articles/RBbmMjY JS组件系列——基于Bootstrap Ace模板的菜单和Tab页效果分享 http://ww ...
- React项目中那些奇怪的写法
1.在一个React组件里看到一个奇怪的写法: const {matchs} = this.props.matchs; 原来,是解构赋值,虽然听说过,但是看起来有点奇怪 下面做个实验: <scr ...