本篇博文主要介绍MongoDB中一些常用的特殊索引类型,主要包括:

  • 用于简单字符串搜索的全文本索引;
  • 用于球体空间(2dsphere)和二维平面(2d)的地理空间索引。

一、全文索引

MongoDB有一个特殊的索引用在文档中搜索文本,之前的博客都是用精确匹配来查询字符串,这些技术有一定的限制。在搜索大块文本的速度非常慢,而且无法处理自然语言礼节的问题。全文本索引使用的是“倒排索引”的思想来做的,和当前非常开源的lucene(全文检索,Apacle基金会下的开源项目)项目是一样的思想来做的。使用全文本索引可以非常快的进行文本搜索,MongoDB支持多种语言,可惜在免费版中,并不支持世界第一的火星文语言(汉语)。查MongoDB的官网可以看到,在企业版中是支持汉语的全文索引的。

如果公司用的是免费版的MongoDB,而又需要用到中文的全文索引,建议使用lucene或者solr等开源项目来做。(没钱就得用技术来补,赤裸裸的现实。)

使用全文本检索需要专门开启这个功能才能进行使用。启动MongoDB时指定--setParameter textSearchEnabled=true选项,或者在运行时执行setParameter命令,都可以启用全文本索引。

db.adminCommand({"setParameter":1,"textSearchEnabled":true});

准备10条数据:

 db.news.insert({"title":"SEOUL","context":"SEOUL, June 10 (Reuters) - South Korean prosecutors raided the offices of Lotte Group, the country's fifth-largest conglomerate, and several affiliates on Friday, dealing a further blow to its hotel unit's planned IPO, billed as the world's biggest this year."});
db.news.insert({"title":"Many Chinese people","context":"Many Chinese people think that a job on a diplomatic team is too good to quit. So when 28-year-old Liu Xiaoxi left her embassy post as an attache late last year to start a career in photography, she quickly became a popular topic among the Chinese online community."});
db.news.insert({"title":"About","context":"About 200 investigators searched 17 locations including group headquarters in central Seoul and the homes of Chairman Shin Dong-bin and other key executives, local news agency Yonhap reported, citing the Seoul Central Prosecutor's office."});
db.news.insert({"title":"Three people","context":"Three people with direct knowledge of the matter told Reuters that Friday's raids were part of an investigation into a possible slush fund. They also declined to be identified."});
db.news.insert({"title":"A Lotte Group spokesman","context":"A Lotte Group spokesman on Friday declined to comment on the reason for the raid, when asked whether it concerned a possible slush fund. He noted, however, that the situation was difficult given the IPO plans and Lotte Chemical's Axiall bid."});
db.news.insert({"title":"According","context":"According to bourse rules, the deadline for Hotel Lotte to list is July 27, six months from the preliminary approval for the IPO. If it needed to refile its prospectus to warn investors about risks from Friday's probe, which appeared likely, it would probably not be able to meet that deadline, an exchange official told Reuters on Friday."});
db.news.insert({"title":"Friday","context":"On Friday, dozens of Chinese tourists queued as usual to access elevators to the flagship Lotte Duty Free outlet in the group's headquarters complex, as TV cameras waited for investigators to emerge from office doors around the corner."});
db.news.insert({"title":"Named","context":"Named after the heroine of an 18th century Goethe novel, Lotte has grown from its founding in Japan 68 years ago as a maker of chewing gum to a corporate giant with interests ranging from hotels and retail to food and chemicals. The group has annual revenue of around $60 billion in Korea."});
db.news.insert({"title":"Hotel Lotte's","context":"Hotel Lotte's planned flotation of around 35 percent of its shares was intended to bring transparency and improve corporate governance at a group whose ownership structure is convoluted even by the opaque standards of South Korea's conglomerates."});
db.news.insert({"title":"Shares","context":"Shares in Lotte Shopping (023530.KS) , whose units Lotte Department Store and Lotte Home Shopping were raided, fell 1.6 percent on Friday. Lotte Himart (071840.KS) , a consumer electronics retailer, dropped 2.1 percent."});

全文索引的数据准备

一个集合上最多只能有一个全文本索引,但是全文本索引可以包含多个字段。全文索引与“普通”的多键索引不同,全文本索引中的字段顺序不重要:每个字段都被同等对待,可以为每个字段指定不同的权重来控制不同字段的相对重要性。

我们来给title和context字段建立全文本索引,给title字段2的权重,context字段1的权重。(权重的范围可以是1~1,000,000,000,默认权重是1)。

db.news.ensureIndex({"title":"text","context":"text"},{"weights":{"title":2,"context":1}})

我们利用这个全文本索引来搜索一下。搜索的内容是“flotation”。

db.news.find({$text:{$search:"flotation"}})

结果如下图所示:

二、2dsphere索引

2dsphere索引是MongoDB最常用的地理空间索引之一,用于地球表面类型的地图。允许使用GeoJSON格式(http://www.geojson.org)指定点、线、多边形。

点可以用形如[longitude,latitude]([经度,纬度])的两个元素的数组表示("loc"字段的名字可以是任意的,但是其中的子对象是有GeoJSON指定的,不能改变):

{
"name":"beijing",
"loc":{
"type":"Point",
"coordinates":[40,2]
}
}

线可以用一个由点组成的数组来表示:

{
"name":"changjiang",
"loc":{
"type":"Line",
"coordinates":[[1,2],[2,3],[3,4]]
}
}

多边形的表示方式与线一样,但是“type”不同:

{
"name":"shenzhen",
"loc":{
"type":"Polygon",
"coordinates":[[1,2],[2,3],[3,4]]
}
}

创建2dsphere索引:

db.mapinfo.ensureIndex({"loc":"2dsphere"})

地理空间查询的类型有三种:交集(intersection)、包含(within)、接近(nearness)。查询时,需要将希望查找的内容指定为形如{"$geometry":geoJsonDesc}的GeoJSON对象。

使用“$geoIntersects”查询位置相交的文档:

var customMapinfo = {
"type":"Polygon",
"coordinates":[[12.2223,39,4424],[13.2223,38,4424],[13.2223,39,4424]]
} db.mapinfo.find({
"loc":{"$geoIntersects":{"$geometry":customMapinfo}}
})

这样就会找到所有与customMapinfo区域有交集的文档。

使用“$within”查询完全包含在某个区域的文档:

db.mapinfo.find({
"loc":{"$within":{"$geometry":customMapinfo}}
})

使用“$near”查询附近的位置:

db.mapinfo.find({
"loc":{"$within":{"$geometry":customMapinfo}}
})

三、2d索引

2d索引也是MongoDB最常用的地理空间索引之一,用于游戏地图。2d索引用于扁平表面,而不是球体表面。如果用在球体表面上,在极点附近会出现大量的扭曲变形。

文档中应该使用包含两个元素的数组表示2d索引字段。

{
"name":"node1",
"tile":[32,22]
}

创建索引

db.gameMapinfo.ensureIndex({"tile":"2d"})

使用$near查询点[20,20]附近的文档:

db.gameMapinfo.find({"tile":{"$near":[20,20]}})

使用$within查询出某个形状(矩形、圆形或者多边形)范围内的所有文档。

矩形,可以指定$box选项($box接受一个两元素的数组,第一个元素指定左下角的坐标,第二个元素指定右上角的坐标):

db.gameMapinfo.find({"tile":{"$within":{"$box":[[10,20],[15,30]]}}})

圆形,可以指定$center选项($center接受一个两元素数组作为参数,第一个元素是一个点,用于指定圆心,第二个元素用于指定半径):

db.gameMapinfo.find({"tile":{"$within":{"$center":[[12,12],5]}}})

多边形,可以指定$polygon($ploygon接受一个多元素的数组,每个元素对应多边形的点),下面以一个三角形为例:

db.gameMapinfo.find({"tile":{"$within":{"$polygon":[[0,20],[10,0],[-10,0]]}}})

 

  喜欢请微信扫描下面二维码,关注我公众号--“精修Java”,做一些实战项目中的问题和解决方案分享。

玩转mongodb(七):索引,速度的引领(全文索引、地理空间索引)的更多相关文章

  1. 学习MongoDB 七: MongoDB索引(索引基本操作)(一)

    一.简介 在MongoDB建立索引能提高查询效率,只需要扫描索引只存储的这个集合的一小部分,并只把这小部分加载到内存中,效率大大的提高,如果没有建立索引,在查询时,MongoDB必须执行全表扫描,在数 ...

  2. 玩转mongodb(九):通过log4jmongo来实现分布式系统的日志统一管理

    背景 在分布式系统中,我们有多个web app,这些web app可能分别部署在不同的物理服务器上,并且有各自的日志输出.当生产问题来临时,很多时候都需要去各个日志文件中查找可能的异常,相当耗费人力. ...

  3. MongoDB数据库索引

    前面的话 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录.这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查 ...

  4. MongoDB数据库索引构建情况分析

    前面的话 本文将详细介绍MongoDB数据库索引构建情况分析 概述 创建索引可以加快索引相关的查询,但是会增加磁盘空间的消耗,降低写入性能.这时,就需要评判当前索引的构建情况是否合理.有4种方法可以使 ...

  5. MongoDb进阶实践之七 MongoDB的索引入门

    一.引言     好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关索引的文章.一说到"索引",用过关系型数据库的人都应该知道它是一个什么 ...

  6. 五、MongoDB的索引

    一.MongoDB的下载.安装与部署 二.MongoDB的基础知识简介 三.MongoDB的创建.更新和删除 四.MongoDB的查询 五.MongoDB的索引 1.简介 它就像是一本书的目录,如果没 ...

  7. 关于mongodb创建索引的一些经验总结(转)

    查看语句执行计划: explain() 在mongodb3+版本后输出格式发生改变: 详情参见:https://docs.mongodb.com/v3.0/reference/method/curso ...

  8. mongodb 的索引

                索引加快了查询速度,但是降低了写入速度.所以不要在没必要的属性上加索引.             在 mongodb 中索引可以按倒序/正序创建,便于排序.           ...

  9. 快速掌握mongoDB(三)——mongoDB的索引详解

    1 mongoDB索引的管理 本节介绍mongoDB中的索引,熟悉mysql/sqlserver等关系型数据库的小伙伴应该都知道索引对优化数据查询的重要性.我们先简单了解一下索引:索引的本质就是一个排 ...

随机推荐

  1. 关于建立MySQL数据库,中文出现乱码问题

    MySQL的ini文件中的默认编码设置utf-8不用改 loose-default-character-set = utf-8 注意:需要改动部分 1.如图所示 建立schema时改变字符编码 改变为 ...

  2. POJ2828线段树单点更新——逆序更新

    Description 输入n个有序对< pi, vi >,pi表示在第pi个位置后面插入一个值为vi的人,并且pi是不降的.输出最终得到的v的序列 Input 多组用例,每组用例第一行为 ...

  3. CI

    做项目时,经常会碰到需要使用php的情况,自己也下决心把php好好学一下. 先从CI开始,再看一下项目中的php代码是如何写的.

  4. Android-Kotlin-具名参数

    先看一个这样的案例,[案例一]: package cn.kotlin.kotlin_base05 fun showAction1(country: String, volk: String) { pr ...

  5. dot net core 使用 IPC 进程通信

    本文告诉大家如何使用dot net core 和其他进程进行通信 一般都是使用 WCF 或 remoting 做远程通信,但是 dot net core 不支持 WCF 所以暂时我就只能使用 管道通信 ...

  6. jzoj4223

    考慮這樣一種暴力:將所有<=x的邊按照類似最小生成樹的方式加入答案,然後用下面的方法統計答案: 1.首先加入一條邊 2.看這條邊是否將會合成聯通塊,如果會,那麼加進這條邊,記這條邊一端聯通塊大小 ...

  7. 前端基础-html 介绍和head标签 ( 1 )

    主要内容 web标准 浏览器介绍 开发工具介绍 HTML介绍 HTML颜色介绍 HTML规范 HTML结构详解 写在前面: 前端               后端 C(client)        S ...

  8. Java Listener中Spring接口注入的使用

    在项目中使用Spring通常使用他的依赖注入可以很好的处理,接口与实现类之间的耦合性,但是通常的应用场景中都是Service层和DAO层,或者web层的话, 也是与Strust2来整合,那么如何在Li ...

  9. Swift 里 Set(四)Testing for Membership

    即contains操作 /// - Parameter member: An element to look for in the set. /// - Returns: `true` if `mem ...

  10. Go指南练习 rot13Reader

    题目: 练习:rot13Reader 有种常见的模式是一个 io.Reader 包装另一个 io.Reader,然后通过某种方式修改其数据流. 例如,gzip.NewReader 函数接受一个 io. ...