Mongodb入门--头歌实验MongoDB 之滴滴、摩拜都在用的索引

MongoDB 常用于大数据的存储,在庞大的数据中查询出我们所要的信息,如果使用普通查询方法,遍历所有文档查询,花费的时间太久了。

假设现在有个集合 person,查询命令:db.person.find( {age: 18} ), 查询所有年龄 18 岁的人,这时需要遍历所有的文档(全表扫描),根据位置信息读出文档,对比 age 字段是否为 18。当然如果只有 4 条文档,全表扫描的开销并不大,但如果集合文档数量到百万、甚至千万上亿的时候,对集合进行全表扫描开销是非常大的,一个查询耗费数十秒甚至几分钟都有可能。这时候我们就需要考虑使用索引了。

其中,地理位置索引支持是 MongoDB 的一大亮点,随着智能手机的兴起,查询当前位置附近的事情变得非常普遍。常见的滴滴、摩拜、OFO 等基于位置进行查询的场景都可以使用 MongoDB 的位置索引。

一、了解并创建一个简单索引

任务描述

本关任务:创建一个单字段索引。

相关知识

为了完成本关任务,你需要掌握: 1.了解索引; 2.索引的分类; 3.如何创建索引。

注:本关实训例子程序请在 mydb 数据库的 person 集合内完成。

了解索引
  • 什么是索引:

索引本质上是树,最小的值在最左边的叶子上,最大的值在最右边的叶子上,使用索引可以提高查询速度(而不用全表扫描)。

  • 索引的原理:

对某个键按照升续或降续创建索引,查询时首先根据查询条件查找到对应的索引条目,然后找到索引条目对应的文档指针(文档在磁盘上的存储位置),根据文档指针再去磁盘中找到相应的文档,整个过程不需要扫描全表,速度比较快。

每个文档被插入集合时,如果没有给它指定索引_id,MongoDB 会自动给它创建一个默认索引_id,是个 ObjectId 对象。如图1所示:

图 1

索引的分类

MongoDB 支持多种类型的索引,主要有以下几种类型:

索引类型用途
包括单字段索引(Single Field Index)针对某一键 key 创建了单字段索引,其能加速对 key 字段的各种查询请求,是最常见的索引形式,MongoDB 默认创建的 id 索引也是这种类型。
复合索引 (Compound Index)复合索引是单字索引的升级版本,它针对多个字段联合创建索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,依次类推。
多 key 索引 (Multikey Index)当索引的字段为数组时,创建出的索引称为多 key 索引。
哈希索引(Hashed Index)按照某个字段的hash值来建立索引,目前主要用于 MongoDB Sharded Cluster 的 Hash 分片,哈希索引只能满足字段完全匹配的查询,不能满足范围查询等。
地理位置索引(Geospatial Index)能很好的解决 O2O 的应用场景,比如:查找附近的美食、查找某个区域内的车站等。
文本索引(Text Index)能解决快速文本查找的需求,比如有一个博客文章集合,需要根据博客的内容来快速查找,则可以针对博客内容建立文本索引。
索引基本操作
  • 创建索引(单字段索引)
db.person.createIndex({key:1})
  • key :要创建索引的键;
  • 如果为 1 说明是按照升序创建索引,而如果为 -1,则是按降序创建索引。

如图2所示,说明创建索引成功:

图2

图 2

  • 查询索引

  • 查询集合索引:

db.person.getIndexes()

效果如图3所示:

图3

图 3

 
  • 查询系统全部索引:
db.system.indexes.find()
  • 删除索引

  • 通过指定索引名称删除该索引:

db.person.dropIndex("ageIdx")

效果如图4所示:

图4

图 4

  • 通过指定集合删除集合中的全部索引:
db.person.dropIndexes()

效果如图5所示:

图5

图 5

 

注:默认索引_id不会且不能被删除

编程要求

根据提示,在右侧命令行进行操作,在 test 数据库创建集合 student ,内容如下:

_idnameagescore
1王小明1590
2周晓晓1886
3王敏2096
4李晓亮1574
5张青青2188

然后在集合中创建成绩的降序索引。

> use test
switched to db test> db.student.insert([{_id:1,name:"王小明",age:15,score:90},{_id:2,name:"周晓晓",age:18,score:86},{_id:3,name:"王敏",age:20,score:96},{_id:4,name:"李晓亮",age:15,score:74},{_id:5,name:"张青青",age:21,score:88}])
BulkWriteResult({"writeErrors" : [ ],"writeConcernErrors" : [ ],"nInserted" : 5,"nUpserted" : 0,"nMatched" : 0,"nModified" : 0,"nRemoved" : 0,"upserted" : [ ]
})> db.student.createIndex({score:-1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}

二、常见索引的创建

任务描述

本关任务:按照编程要求创建不同的索引。

相关知识

为了完成本关任务,你需要掌握: 1.创建复合索引; 2.创建多 key 索引; 3.创建哈希索引; 4.文本索引创建与使用(重点)。

注:本关实训例子程序请在 mydb2 数据库内完成。

创建复合索引

和创建单字段索引的方法差不多,只是选取了多个键一同作为索引,中间以逗号隔开:

db.person.createIndex({age: 1, name: 1})

用法也和单字段索引差不多,就不再赘述。

创建多 key 索引

当索引的字段为数组时,创建出的索引称为多 key 索引,多 key 索引会为数组的每个元素建立一条索引,比如 person 集合加入一个 habbit 字段(数组)用于描述兴趣爱好:

{name : '王小明', age : 19, habbit: ['football', 'runnning']}

需要查询有相同兴趣爱好的人就可以利用 habbit 字段的多 key 索引。

db.person.createIndex( {habbit: 1} )     // 升序创建多key索引
db.person.find({habbit: 'football'})     //查找喜欢足球的人
创建哈希索引

创建命令如下:

db.person.createIndex( { _id: 'hashed' } )

注:哈希索引涉及知识点太多,本关就不做重点介绍,以后用到再做详细解释。

文本索引的创建与使用
  • 什么时候使用文本索引;

假如我们用 Mongodb 存储了很多博客文章,那么如何快速找到所有关于 mongodb 这个主题的文章呢?这时候就要用到文本搜索了。

有文章集合 collection,如下:

{title: 'enjoy the mongodb articles on educoder',tags: ['mongodb','educoder']
}

创建文本索引命令,如下:

db.collection.createIndex({ title: 'text'})
  • 创建全文本索引的字段必须为 string 格式;
  • 每个集合只支持一个文本索引。

运行效果如图1所示:

图1

图 1

也可以创建多个字段的 text,下面的示例在字段主题和注释上创建一个文本索引:

db.collection.createIndex({title:'text',tags:'text'}
)
  • 使用文本索引;

现在我们已经创建了 title 的索引,我们来搜索一下含有 educoder.net 的文章:

db.collection.find({$text:{$search:'educoder.net'}})
  • search 后的关键词可以有多个,关键词之间的分隔符可以是多种字符,例如空格、下划线、逗号、加号等,但不能是-\,因为这两个符号会有其他用途。搜索的多个关键字是 or 的关系,除非你的关键字包含-
  • 匹配时不是完整的单词匹配,相似的词也可以匹配到;

运行效果如图2所示:

图 2

  • 删除文本索引;

  • 通过命令获取索引名:

    db.collection.getIndexes()
  • 删除命令:

    db.collection.dropIndex('title_text')

    运行效果如图3所示:

    图3

    图 3

编程要求

根据提示,在右侧命令行进行操作,在 test2 数据库中创建集合 article,内容如下:

_idtitletagsfollwers
1提升程序员工作效率的6个工具利器Alfred,幕布543
2我是如何从零开始学习前端的HTML,Html5,CSS1570
320个非常有用的JAVA程序片段Java,编程1920

集合创建完成后,按要求创建以下索引:

  • 用字段 follwers 和 title 创建复合升序索引;

  • 用字段 tags 创建多 key 降序索引;

  • _id创建哈希索引;

  • 用字段 title 和 tags 创建文本索引。

> use test2
switched to db test2> db.article.insert([
{_id:1,title:"提升程序员工作效率的6个工具利器",tags:["Alfred","幕布"],follwers:543},
{_id:2,title:"我是如何从零开始学习前端的",tags:["HTML","Html5","CSS"],follwers:1570},
{_id:3,title:"20个非常有用的JAVA程序片段",tags:["Java","编程"],follwers:1920}])
BulkWriteResult({"writeErrors" : [ ],"writeConcernErrors" : [ ],"nInserted" : 3,"nUpserted" : 0,"nMatched" : 0,"nModified" : 0,"nRemoved" : 0,"upserted" : [ ]
})> db.article.createIndex({follwers:1,title:1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1
}> db.article.createIndex({tags:-1})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 2,"numIndexesAfter" : 3,"ok" : 1
}> db.article.createIndex({_id:'hashed'})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 3,"numIndexesAfter" : 4,"ok" : 1
}> db.article.createIndex({title:'text',tags:'text'})
{"createdCollectionAutomatically" : false,"numIndexesBefore" : 4,"numIndexesAfter" : 5,"ok" : 1
}

 三、有趣的地理位置索引

任务描述

本关任务:查看我们距离哪所大学最近。

相关知识

为了完成本关任务,你需要掌握: 1.什么是 GeoJson 数据; 2.如何创建地理位置索引; 3.如何使用地理位置索引。

注:本关实训例子程序请在 mydb3 数据库内完成。

GeoJson 数据

并不是所有文档都可以创建地理位置索引,只有拥有特定格式的文档才可以创建。

如果我们用的是 2dsphere 索引,那么插入的应该是 GeoJson 数据。GeoJson 的格式如是: { type: 'GeoJSON type' , coordinates: 'coordinates' }

  • type :指的是类型,可以是 Point (本例中用的)、LineString、 Polygon 等;

  • coordinates :指的是一个坐标数组。

我们有如下几个位置的坐标信息(具体详情如图1所示),先把它们写入集合 locations 中。

db.locations.insert({_id:1,name:'长沙站',location:{type:'Point',coordinates:[113.018987,28.201215]}})
db.locations.insert({_id:2,name:'湖南师范大学',location:{type:'Point',coordinates:[112.946045,28.170968]}})
db.locations.insert({_id:3,name:'中南大学',location:{type:'Point',coordinates:[112.932175,28.178291]}})
db.locations.insert({_id:4,name:'湖南女子学院',location:{type:'Point',coordinates:[113.014675,28.121163]}})
db.locations.insert({_id:5,name:"湖南农业大学",location:{type:'Point',coordinates:[113.090852,28.187461]}})

图1

图 1

创建地理位置索引

有了规范的文档后,我们就可以使用以下命令,在 location 键上创建一个地理位置索引:

db.locations.createIndex({location:'2dsphere'})
  • 2d :平面坐标索引,适用于基于平面的坐标计算,也支持球面距离计算,不过官方推荐使用 2dsphere 索引;

  • 2dsphere :几何球体索引,适用于球面几何运算;

  • 默认情况下,地理位置索引会假设值的范围是从−180到180(根据经纬度设置)。

如下索引创建成功,效果如图2所示:

图2

图 2

地理位置索引的使用

查询命令:

db.runCommand({geoNear:'locations',near:{type:'Point',coordinates:[113.018987,28.201215]},spherical:true,minDistance:1000,maxDistance:8000})
  • geoNear :我们要查询的集合名称;

  • near :就是基于那个点进行搜索,这里是我们的搜索点“长沙站”;

  • spherical :是个布尔值,如果为 true,表示将计算实际的物理距离,比如两点之间有多少 km,若为 false,则会基于点的单位进行计算 ;

  • minDistance :搜索的最小距离,这里的单位是米 ;

  • maxDistance :搜索的最大距离。

查询结果分析:

在 result 中,查到了“湖南农业大学”和“湖南师范大学”,每个文档都加上了一个 dis 字段,它表示这个点离你搜索点的距离。比如说,在结果中 name 为“湖南农业大学”的点的 dis 为7215.061630510019。表示“湖南农业大学”距离搜索点“长沙站”的距离是7215米。这个结果对于 LBS 应用是非常有用的。具体详情如图3所示:

图3

图 3

编程要求

如图4所示,有6个人 A、B、C、D、E、F 的位置,请将这些位置信息插入到数据库 test3 的集合 people 中,并建立地理位置索引 personloc。

  • 查询 A 周围100~3000米有哪些人;

  • 查询 B 周围100~5000米有哪些人;

  • 查询 C 周围3000~8000米有哪些人;

  • 查询 D 周围3000~8000米有哪些人。

图4

图 4

 

请逐条插入以下信息和位置 GeoJson 数据:

{_id:1,name:'A',personloc:{type:'Point',coordinates:[116.403981,39.914935]}}
{_id:2,name:'B',personloc:{type:'Point',coordinates:[116.433733,39.909511]}}
{_id:3,name:'C',personloc:{type:'Point',coordinates:[116.488781,39.949901]}}
{_id:4,name:'D',personloc:{type:'Point',coordinates:[116.342609,39.948021]}}
{_id:5,name:'E',personloc:{type:'Point',coordinates:[116.328236,39.901098]}}
{_id:6,name:'F',personloc:{type:'Point',coordinates:[116.385728,39.871645]}}
echo "
db.people.insert({_id:1,name:'A',personloc:{type:'Point',coordinates:[116.403981,39.914935]}});
db.people.insert({_id:2,name:'B',personloc:{type:'Point',coordinates:[116.433733,39.909511]}});
db.people.insert({_id:3,name:'C',personloc:{type:'Point',coordinates:[116.488781,39.949901]}});
db.people.insert({_id:4,name:'D',personloc:{type:'Point',coordinates:[116.342609,39.948021]}});
db.people.insert({_id:5,name:'E',personloc:{type:'Point',coordinates:[116.328236,39.901098]}});
db.people.insert({_id:6,name:'F',personloc:{type:'Point',coordinates:[116.385728,39.871645]}});
db.people.createIndex({personloc:'2dsphere'});
db.runCommand({geoNear:'people',near:{type:'Point',coordinates:[116.403981,39.914935]},spherical:true,minDistance:100,maxDistance:3000});
db.runCommand({geoNear:'people',near:{type:'Point',coordinates:[116.433733,39.909511]},spherical:true,minDistance:100,maxDistance:5000});
db.runCommand({geoNear:'people',near:{type:'Point',coordinates:[116.488781,39.949901]},spherical:true,minDistance:3000,maxDistance:8000});
db.runCommand({geoNear:'people',near:{type:'Point',coordinates:[116.342609,39.948021]},spherical:true,minDistance:3000,maxDistance:8000});
"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/808487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

libVLC 视频窗口上叠加透明窗口

很多时候,我们需要在界面上画一些三角形、文字等之类的东西,我们之需要重写paintEvent方法,比如像这样 void Widget::paintEvent(QPaintEvent *event) 以下就是重写的代码。 void Widget::paintEvent(QPaintEvent *event) {//创建QPainte…

振动信号频域图绘制函数(python版)

在实际应用中,不免会看时域图和频域图,封装了绘制时域图和频域图程序,方便调用 ## 导入包 from matplotlib import pyplot as plt from matplotlib import rcParams import numpy as np import pandas as pdconfig {"font.family"…

创新指南|战略衡量的增长组织:用人工智能增强关键绩效指标(KPI)

传统的关键绩效指标 (KPI)越来越无法提供领导者取得成功所需的信息和见解。他们在跟踪进展、协调人员和流程、确定资源优先级以及推进问责制方面存在不足。本文是 2024 年第一份麻省理工学院 SMR - BCG 人工智能和商业战略全球高管学习和研究项目的调查结果——人工智能和业务战…

最新PDD商家端Anti-Content参数逆向分析与纯算法还原

文章目录 1. 写在前面2. 接口分析3. 断点分析4. 扣JS代码 【🏠作者主页】:吴秋霖 【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致…

第十五篇:Mybatis

文章目录 一、什么是MyBatis二、Mybatis入门案例三、配置SQL提示四、数据库连接池四、lombok五、mybatis基础操作5.1 根据id删除5.2 预编译SQL5.3 新增员工5.4 更新员工5.5 查询员工(用于页面回显)5.6 条件查询 七、XML映射文件八、动态SQL8.1 if语句8.2…

(学习日记)2024.04.12:UCOSIII第四十节:软件定时器函数接口讲解

写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…

JavaScript_语法--变量

1.4 变量 变量:一小块存储数据的内存空间 Java语言是强类型语言,而JavaScript是弱类型的语言 强类型: 在开辟变量存储空间时,定义了空间将来存储的数据的数据类型。只能存储固定类型的数据 弱类型: 在开辟变量存储空间…

VS中使用QT的UI提升类时,找不到头文件的情况

1、情况简述 在使用VS时,会发现与QCreator存在一些差异。最主要的就是要设置很多东西,如果不配置的话,就会遇到一些问题。下面我分享下我调试过程中遇到的一个问题。使用Qdesigner的UI提升类时,找不到头文件的情况: …

Kivy 学习2

from kivy.app import App from kivy.uix.button import Button from kivy.uix.floatlayout import FloatLayout from kivy.graphics import Rectangle, Colorclass FloatLayoutApp(App):def build(self):def update_rect(layout, *args):设置背景尺寸,可忽略layout…

Spring Cloud学习笔记:Eureka简介,Eureka简单样例

这是本人学习的总结,主要学习资料如下 - 马士兵教育 [TOC](目录)1、Eureka 1.1、架构 Eureka是SpringCloud Nexflix的核心子模块,其中包含Server和Client。 Server提供服务注册,存储所有可用服务节点。 Client用于简化和Server的通讯复杂…

【学习心得】Python中的queue模块使用

一、Queue模块的知识点思维导图 二、Queue模块常用函数介绍 queue模块是内置的,不需要安装直接导入就可以了。 (1)创建一个Queue对象 import queue# 创建一个队列实例 q queue.Queue(maxsize20) # 可选参数,默认为无限大&am…

物理随机接入信道PRACH数据生成

NR随机接入前导码(Preamble)采用Zadoff Chu序列,长度分别为839和139。 物理随机接入信道(PRACH)前导码格式的定义包括PRACH OFDM符号个数、循环前缀(CP)长度和保护时间(GT&#xff…

软件库V1.2版本开源-首页UI优化

iAppV3源码,首页的分类更换成了标签布局,各位可以参考学习,界面名称已经中文标注! 老版本和现在的版本还是有较大的区别的,建议更新一下! 新版本改动界面如下: 1、首页.iyu:分类按…

Windows:Redis数据库图形化中文工具软件——RESP(3)

这个是用于连接redis数据库的软件工具,安装在windows上的图形化界面,并且支持中文,是在github上的一个项目 1.获取安装包 发布 lework/RedisDesktopManager-Windows (github.com)https://github.com/lework/RedisDesktopManager-Windows/rel…

Java复习第十八天学习笔记(MVC,三层架构,分页),附有道云笔记链接

【有道云笔记】十八 4.4 MVC模式、三层架构、分页 https://note.youdao.com/s/PRQ62OUV 一、MVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范, 用一种业务…

C++ 为什么不能在构造函数中调用虚函数

最近在Clion编辑器中看到构造函数中调用虚函数提示&#xff1a; Do not invoke virtual member functions from constructor 这里记录一下为什么不能在构造函数中调用虚函数。 #include <iostream> #include <string>using namespace std;class BaseClass {publi…

超越ChatGPT,国内快速访问的强大 AI 工具 Claude

claude 3 opus面世后&#xff0c;网上盛传吊打了GPT-4。网上这几天也已经有了许多应用&#xff0c;但竟然还有很多小伙伴不知道国内怎么用gpt&#xff0c;也不知道怎么去用这个据说已经吊打了gpt-4的claude3。 今天我们想要进行的一项尝试就是—— 用claude3和gpt4&#xff0c…

2024年第十七届 认证杯 网络挑战赛 (C题)| 云中的海盐 | 辐射传输方程 Stefan-Boltzmann分析 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看认证杯 网络挑战赛 (C题&#xff09;&#xff01…

SQL Serve---查询

概要 1、order by子句 —默认asc&#xff08;升序&#xff09;、desc&#xff08;降序&#xff09; 2、distinct关键字 3、group by子句 4、聚合函数 —max()、min()、sum()、avg()、count() 5、having子句 6、compute子句 英文关键字 order by 排序 asc…

【无标题】nodejs+mogoodb数据库写注册接口

描述 本篇文章主要记录使用nodejs express搭建服务器&#xff0c;并链接mogoodb数据来书写简单的后台接口&#xff1b;前端项目使用的vue2的一个酒店管理项目。阅读本文章&#xff0c;可以了解如何连接mogoodb数据库&#xff0c;和一些对数据库进行操作的命令。前端如何进行跨…