mongoDB中的特殊索引

本片文章,主要去了解一下mongoDB中一些相对特殊的索引。使用面没那么广,适用于特定场合下,比如类队列数据的固定集合、TTL索引、简单字符串搜索的全文本索引等,这种情形下,会有对应的特殊索引.

1. mongoDB中固定集合
  • 固定集合的特点和创建方式
    mongodb中 普通集合是可以动态创建的,可以自增长。此外,mongodb中也有 一种固定大小的集合,叫固定集合

    • 在创建的时候,指定大小,

    • 类似循环队列 (环形),当数据满了,再插入时,会把最开始的document删除
      mongodb这种特性,适用于任何想要自动淘汰过期数据的集合,比如 日志记录、监控记录、行车记录、通话记录等

    • 创建语句
      基本语法:

      db.createCollection("集合名词",{capped:true,size:1000,max:100}); 
      

      参数 :

      • capped : true 表示该集合为固定集合
      • size : 指定集合大小,单位为KB
      • max : 指定文档的数量
        db.createCollection("logsQueue",{capped:true,size:100000,max:100});
        for(var i=0;i<100;i++){ db.logsQueue.insert({count: i}); }; // 先插入99条数据
        db.logsQueue.find() 
        
    • 替换旧document示例
      上边创建了一个固定集合,并且插入了99条数据,之后,再插入一条数据,发现最开始的第一条数据已经被删除了,测试过程如下

      > db.logsQueue.find()
      // .... 第一条数据是 {count : 0}
      > db.logsQueue.insert({t:1})
      > db.logsQueue.find()
      // .... 第一条数据是{ count : 1 }发现{count : 0}这条记录已经被删除了
      
      • 注意
      1. 创建固定集合时,限制了集合的大小(size)、集合的文档数量(max), 无论是 先到了size限制,还是先到了文档数量限制,都会将旧文档删除,插入新文档
      2. 固定集合的结构决定了固定集合不可以分片
  • 固定集合的自然排序
    对固定集合来说,可以进行一种特殊排序,成为自然排序,不同于普通的集合,固定集合是文档是按照插入顺序保存的, 因此它可以按照从旧到新、或者从新到旧排序,如下

    db.fixCollection.find().sort({"$natural":-1})
    
2 . TTL索引
  • 和固定集合比较
    对于固定集合做一个类比, 固定集合如果文档不满是不会被替代的,而TTL索引就可以更加灵活的 老化移除(age-out),
    TTL全称是 ”time-to-live index“ : 具有生命周期的索引 , 创建的语法如下
    db.peo.ensureIndex({lastUpdated:1},{"expireAfterSecs":60*60*24})
    
    上边的索引意思是 : 当服务器时间比文档的lastUpdated字段晚expireAfterSecs的值,文档就会删除。
    mongoDB每分钟对TTL索引,进行一次清理, 换句话说,不应该依赖以秒为单位的时间保证索引存活状态
3. 全文本索引
  • 创建全文本索引开销
    创建任何一种索引,都会需要很高的开销,尤其是经常修改的集合。创建全文本索引的时候,要特别小心,内存可能会不够
    全文本索引,可能会导致更严重性能问题,因为它会把所有字符串分解、分词、并且保存到一些地方。因此,拥有全文本索引的集合的写入会比其他集合要差

  • 不同版本的创建方式不同
    第一次使用全文索引时,没注意到使用的mongodb版本和资料不同,因此一直没有创建成功,后来发现,对于mongodb来说:
    在 2.6 版本以后是默认开启全文检索的;
    2.6版本之前,可以用如下的命令

    >db.adminCommand({setParameter:true,textSearchEnabled:true}) 
    // 一定注意,这条命令是2.6之前的,2.6之后的默认开启,无需调用
    

    好的,那我们直接测试全文本索引 ,如下创建数据格式,创建对应的全文本索引

     db.peo.insertOne({"post_text":"enjoy the mongodb articles on Runoob","tags":["mongodb","runoob"]})
     //创建全文本索引
     db.peo.ensureIndex({post_text:"text"})
    

    接下来搜索一下, 看是否可以根据文本查询到这条记录

    //搜索文本
     > db.peo.find({$text:{$search:"runoob"}})
    { "_id" : ObjectId("5d8da6cbfa4e34df34f24b3a"), "post_text" : "enjoy the mongodb articles on Runoob", "tags" : [ "mongodb", "runoob" ] }
    

    不过,当我查询the的时候,发现查询不到,其他的词语都可以

    //搜索文本
     > db.peo.find({$text:{$search:"articles"}})
    { "_id" : ObjectId("5d8da6cbfa4e34df34f24b3a"), "post_text" : "enjoy the mongodb articles on Runoob", "tags" : [ "mongodb", "runoob" ] }
    > db.peo.find({$text:{$search:"the"}})
    //the作为关键字,发现查询不到
    

    后来查询资料,部分说 ”the”在英语分词里被当做stop words处理了,根本不会写入索引,更不会参与查询的 。 这里需要注意一下

  • 全文本索引一些细节
    资料上说,mongodb用的是开源的snowball分词器 , 这个分词器是支持很多语言的,默认支持英语 , 对汉语支持不是很好。接下来,测试一下汉语的支持程度

    > db.test1.insertMany([{name:'中国'},{name:'中国 你好'},{name:'你好,中国'},{name:'五千年中国文化'}])
    > db.test1.ensureIndex({name:"text"})
    > db.test1.find({$text:{$search:" 中国 "}})
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b3f"), "name" : "中国" }
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b41"), "name" : "你好,中国" }
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b40"), "name" : "中国 你好" }
    > db.test1.find()
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b3f"), "name" : "中国" }
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b40"), "name" : "中国 你好" }
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b41"), "name" : "你好,中国" }
    { "_id" : ObjectId("5d8dac76fa4e34df34f24b42"), "name" : "五千年中国文化" 			}
    > 
    

    很显然,中文是可以用的,不过,看结果来说,如果一句话没有分隔符的话,估计是不会给拆开,因为汉语和英语不同的地方就是,英语单词之间肯定是用空格,但是汉语… 仁者见仁智者见智吧

  • 总结一下全文索引的特点
    创建语法 :

    db.collectionName.ensureIndex({attributeName:"text"})
    //collectionName : 集合名称 ; attributeName : document中字段名称
    

    查询语法

    db.collectionName.find("$text":{"$search":str})
    //str : 要查询的字符串
    
4. 一些更专业性的索引

专业性,换句话说,就是冷门,适用于专门的场景下,博主在实际开发中几乎没用到,也没啥印象,如果不是看mongodb权威指南,估计都不知道,惭愧惭愧

  • 先说一下,地理空间
    mongodb支持多种地理空间索引,常用的是2dsphere。 2dsphre允许使用GeoJSON格式指定点、线、多边形, 格式如下

    //  loc字段名是任意的,但是它的子对象是GeoJSON指定,不可改变
    //点 : [精度、纬度
    {"name":"new york",
      "loc":{
      		"type":"Point", 
      		 "coordinates":[50,2]
      	}
    }
    //线 由点组成 , 大于等于两个点,表示
    {"name":"Hudson River",
      "loc":{
      		"type":"Line", 
      		 "coordinates":[[0,2],[0.1],[1.2]]
      	}
    }
    //多边形 和线写法类似,只是type写法不一样
    {"name":"Hudson River",
      "loc":{
      		"type":"Polygon", 
      		 "coordinates":[[0,2],[0.1],[1.2]]
      	}
    }
    
  • 2dsphree如何创建地理空间索引,如何进行查询

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

    地理空间查询,基本用法如下
    查询的时候,需要将希望查询的内容指定为形如{"$geometry":geoJsonDesc},
    组合上“$geoIntersects” (交集 )、“$within” (包含 )、“$near” (附近 )

    //比如一个地区
    var eastVillage = {"type":"Polygon", "coordinates":[[-73.9917900,40.7264100],[-73.9917900,40.7321400], [-73.9829300,40.7321400]]}
    

    比如查找 和上边代码相近的地方

    //有交集 
    {"$geoIntersects":{"$geometry":eastVillage}}
    //完全包含
    {"$within":{"$geometry":eastVillage}}
    //附近的
    {"$near":{"$geometry":eastVillage}}
    

    而2dsphere 是对点进行索引,可以保存一个由点组成的数组,不会被当做线

5. GridFS : MongoDB中存储大文件
  • GridFS
    是MongoDB中一种存储机制,用于存储大型二进制文件。优点很多,比如自动平衡已有的复制或者为MongoDB设置的自动分片,;在用户上传文件时,剞劂一些文件系统可能会遇到问题;存储数据比较大

  • 使用
    可以使用mongofiles工具,基本操作有三个 put、 list、get 。
    可以在shell中或者一些驱动程序中使用,shell中使用如下,一些驱动程序中,用法类似,具体细节可以参考对应驱动的文档

    > mongofiles put foo.txt
    > mongofiles list
    > mongofiles get foo.txt
    
  • 存储格式
    GridFS是一种轻量级文件存储规范,存储MongoDB中普通文档,需要注意的是基本上所有的处理都在客户端,由驱动程序和工具负责,服务器端几乎不需处理
    基本思路是 : 把大文档拆分成单独存储的小文档,然后加一个文档存储各个小文档的信息,数据格式大体如下

    {	_id : 文档自带id, 
    	n :块在文件中相对位置,比如0或者1或者2...
    	data : 块中包含的二进制数据
    	files_id : 块所属文件原信息
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值