小于博客 小于博客
首页
  • Java学习笔记
  • Docker专区
  • 实战教程
  • Shell
  • 内存数据库
  • Vue学习笔记
  • Nginx
  • Php
  • CentOS
  • Docker
  • Gitlab
  • GitHub
  • MySql
  • MongoDB
  • OpenVPN
  • 配置文件详解
  • Other
  • ELK
  • K8S
  • Nexus
  • Jenkins
  • 随写编年
  • 电影音乐
  • 效率工具
  • 博客相关
  • 最佳实践
  • 迎刃而解
  • 学习周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • 网站状态 (opens new window)
    • json2go (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)

小于博客

行者常至,为者常成
首页
  • Java学习笔记
  • Docker专区
  • 实战教程
  • Shell
  • 内存数据库
  • Vue学习笔记
  • Nginx
  • Php
  • CentOS
  • Docker
  • Gitlab
  • GitHub
  • MySql
  • MongoDB
  • OpenVPN
  • 配置文件详解
  • Other
  • ELK
  • K8S
  • Nexus
  • Jenkins
  • 随写编年
  • 电影音乐
  • 效率工具
  • 博客相关
  • 最佳实践
  • 迎刃而解
  • 学习周刊
关于
友链
  • 本站索引

    • 分类
    • 标签
    • 归档
  • 本站页面

    • 导航
    • 打赏
  • 我的工具

    • 备忘录清单 (opens new window)
    • 网站状态 (opens new window)
    • json2go (opens new window)
    • 微信MD编辑 (opens new window)
    • 国内镜像 (opens new window)
    • 出口IP查询 (opens new window)
    • 代码高亮工具 (opens new window)
  • 外站页面

    • 开往 (opens new window)
    • ldapdoc (opens new window)
    • HowToStartOpenSource (opens new window)
    • vdoing-template (opens new window)
GitHub (opens new window)
  • Nginx

  • Php

  • CentOS

  • Docker

  • GitLab

  • GitHub

  • Mysql

  • MongoDB

    • 认识了解MongoDB
    • CentOS-7部署MongoDB
    • MongoDB增删改查基本操作
    • MongoDB日常运维之用户管理
    • MongoDB索引方面的学习实践
      • 准备数据
      • 创建索引
      • 数据查询
      • 其他进阶
        • 数组索引
        • 全文索引
        • 其他补充
    • MongoDB关联查询的学习以及实践
  • OpenVPN

  • 配置文件详解

  • Other

  • 运维观止
  • MongoDB
小于博客
2022-02-27
目录

MongoDB索引方面的学习实践

cmdb使用MongoDB作为底层数据存储,为了便于检索,本文将探讨研究一些MongoDB的索引使用。

# 准备数据

在开始学习了解之前,先准备一些测试数据如下:

db.datas.insert(
    [
        {"datas_identify":"eryajf","data":[{"name":"aaa","identify":"aaa-1","create_time":"2020-01-01"}]},
        {"datas_identify":"eryajf","data":[{"name":"bbb","identify":"bbb-1","create_time":"2021-01-01"}]},
        {"datas_identify":"eryajf","data":[{"name":"ccc","identify":"ccc-1","create_time":"2022-01-01"}]},
        {"datas_identify":"eryajf","data":[{"name":"ddd","identify":"ddd-1","create_time":"2023-01-01"}]},
        {"datas_identify":"eryajf","data":[{"name":"eee","identify":"eee-1","create_time":"2024-01-01"}]},
        {"datas_identify":"liql","data":[{"name":"fff","identify":"fff-1","create_time":"2024-01-01"}]},
        {"datas_identify":"liql","data":[{"name":"ggg","identify":"ggg-1","create_time":"2026-01-01"}]},
        {"datas_identify":"liql","data":[{"name":"hhh","identify":"hhh-1","create_time":"2027-01-01"}]},
        {"datas_identify":"liql","data":[{"name":"iii","identify":"iii-1","create_time":"2028-01-01"}]},
        {"datas_identify":"liql","data":[{"name":"aaa","identify":"aaa-1","create_time":"2029-01-01"}]}])
1
2
3
4
5
6
7
8
9
10
11
12

常规情况下,我们可以针对具体字段进行查询:

db.getCollection('datas').find({"datas_identify":"eryajf"})
db.getCollection('datas').find({"data.name":"aaa"})
1
2

这种针对指定字段的查询没有问题,不过如果想要实现一个智能识别的,或者针对当前数据表能够全表搜索的,就需要用到索引了。

# 创建索引

MongoDB可以对任意字段建立全文索引(text index),但需要注意:1个collection中只能包含至多1个全文索引,且只能对String或String数组的字段建立文本索引。

我们可以通过如下命令创建一个文本索引:

db.datas.createIndex({datas_identify: "text"})
1

这个语句表示将datas_identify字段添加为全文索引,当然也可以指定多个字段,方法如下:

db.datas.createIndex({datas_identify: "text", name: "text"})
1

执行完毕之后,可以通过如下命令查看当前集合的索引:

$ db.datas.getIndexes()

/* 1 */
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_"
    },
    {
        "v" : 2,
        "key" : {
            "_fts" : "text",
            "_ftsx" : 1
        },
        "name" : "datas_identify_text",
        "weights" : {
            "datas_identify" : 1
        },
        "default_language" : "english",
        "language_override" : "language",
        "textIndexVersion" : 3
    }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  • 索引创建之后默认支持的语言是英文,需要注意,MongoDB目前还不支持中文,点击这里 (opens new window)可以查看当前支持的语言列表。
  • 当索引字段有多个的时候,可以通过weights字段控制索引字段的权重。

# 数据查询

查询的语句格式如下:

{  
 $text:  
 	{  
		$search: <string>,  
		$language: <string>,  
		$caseSensitive: <boolean>,  
		$diacriticSensitive: <boolean>  
 	}  
}
1
2
3
4
5
6
7
8
9
  • $search:后面跟的是将要搜索的关键字。
  • $language:指定搜索的语言。
  • $caseSensitive:设置是否区分大小写。
  • $diacriticSensitive设置是否区别发音符号。

那么查询 datas_identify为eryajf的方式如下:

$ db.datas.find({ $text: {$search: "eryajf"}})
1

# 其他进阶

# 数组索引

MongoDB可以给一个数组添加索引,从而提高指定数组的检索效率。

创建一个数组的索引:

$ db.datas.createIndex({"data.name":"text","data.identify":"text","datas_identify":"text"})
1

然后直接进行检索:

$ db.datas.find({ $text: {$search: "bbb"}})
/* 1 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebd6"),
    "datas_identify" : "eryajf",
    "data" : [ 
        {
            "name" : "bbb",
            "identify" : "bbb-1",
            "create_time" : "2021-01-01"
        }
    ]
}


$ db.datas.find({ $text: {$search: "aaa"}})
/* 1 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebde"),
    "datas_identify" : "liql",
    "data" : [ 
        {
            "name" : "aaa",
            "identify" : "aaa-1",
            "create_time" : "2029-01-01"
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebd5"),
    "datas_identify" : "eryajf",
    "data" : [ 
        {
            "name" : "aaa",
            "identify" : "aaa-1",
            "create_time" : "2020-01-01"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

这是在明确知道数组内字段的情况下的方案,在一些实际应用场景中,一个数组内的字段有可能是不固定的,这种时候就没办法对指定字段进行索引了。这个时候就需要用到全文索引了。

# 全文索引

建立一个通配符全文索引的方法是:

$ db.datas.createIndex({"$**":"text"})
1

全文索引创建完毕之后,我们可以对整个集合进行检索。

测试效果如下:

$ db.datas.find({ $text: { $search: "aaa" } })
/* 1 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebde"),
    "datas_identify" : "liql",
    "data" : [ 
        {
            "name" : "aaa",
            "identify" : "aaa-1",
            "create_time" : "2029-01-01"
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebd5"),
    "datas_identify" : "eryajf",
    "data" : [ 
        {
            "name" : "aaa",
            "identify" : "aaa-1",
            "create_time" : "2020-01-01"
        }
    ]
}

# ============ #

$ db.datas.find({ $text: { $search: "2022" } })
/* 1 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebd7"),
    "datas_identify" : "eryajf",
    "data" : [ 
        {
            "name" : "ccc",
            "identify" : "ccc-1",
            "create_time" : "2022-01-01"
        }
    ]
}

# ============ #

$ db.datas.find({ $text: { $search: "2024" } })
/* 1 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebda"),
    "datas_identify" : "liql",
    "data" : [ 
        {
            "name" : "fff",
            "identify" : "fff-1",
            "create_time" : "2024-01-01"
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("621b7bbff00df89221ebebd9"),
    "datas_identify" : "eryajf",
    "data" : [ 
        {
            "name" : "eee",
            "identify" : "eee-1",
            "create_time" : "2024-01-01"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

# 其他补充

基于全文索引的搜索,有一些需要注意的点,这里做一下记录。

  • 如果查询中有通配符,使用如下方式转义
    $ db.datas.find({ $text: { $search: "\"10.6.6.66\"" } })
    
    1
  • 多条件逻辑或
    $ db.datas.find({ $text: { $search: "2024 bbb" } })
    
    1
  • 多条件逻辑与
    $ db.datas.find({ $text: { $search: '"2024" "liql"' } })
    
    1
  • 如果想要排除某个结果,则用-查询
    $ db.datas.find({ $text: { $search: '"2024" -liql' } })
    /* 1 */
    {
    	"_id" : ObjectId("621b7bbff00df89221ebebd9"),
        "datas_identify" : "eryajf",
        "data" : [ 
            {
    	        "name" : "eee",
        	    "identify" : "eee-1",
            	"create_time" : "2024-01-01"
            }
        ]
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
  • golang检索时的代码
    type Data struct {
    	DatasIdentify string `json:"datas_identify"`
    	Data          []struct {
    		Name       string `json:"name"`
    		Identify   string `json:"identify"`
    		CreateTime string `json:"create_time"`
    	} `json:"data"`
    }
    
    func FindTest() {
    	filters := bson.D{}
    	filter := bson.E{Key: "datas_identify", Value: "eryajf"}
    	searchFilter := bson.E{Key: "$text", Value: bson.M{"$search": "2022"}}
    	filters = append(filters, filter, searchFilter)
    	datas, err := ListData(filters, options.FindOptions{})
    	if err != nil {
    		fmt.Printf("get data failed: %v\n", err)
    	}
    	for _, v := range datas {
    		fmt.Println(v)
    	}
    
    }
    
    // ListData 获取数据列表
    func ListData(filter bson.D, options options.FindOptions) ([]*Data, error) {
    	table := DB.Collection("datas")
    	cus, err := table.Find(ctx, filter, &options)
    	if err != nil {
    		fmt.Printf("find data failed: %v\n", err)
    	}
    	defer func(cus *mongo.Cursor, ctx context.Context) {
    		err := cus.Close(ctx)
    		if err != nil {
    			return
    		}
    	}(cus, ctx)
    
    	list := make([]*Data, 0)
    	for cus.Next(ctx) {
    		data := new(Data)
    		err := cus.Decode(&data)
    		if err != nil {
    			fmt.Printf("decode data failed: %v\n", err)
    		}
    		list = append(list, data)
    	}
    
    	return list, nil
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

以上就是MongoDB中索引的一些实践,一些内容需要结合实际场景进行使用。

  • 参考:
    • MongoDB全文搜索 (opens new window)
    • Mongodb全文搜索实战 (opens new window)
    • MongoDB之索引 (opens new window)
    • MongoDB中的全文本搜索 (opens new window)
    • 通配符索引 (opens new window)
    • How to AND and NOT in MongoDB $text search (opens new window)
#MongoDB
上次更新: 2024/01/11, 14:21:50

← MongoDB日常运维之用户管理 MongoDB关联查询的学习以及实践→

最近更新
01
SpringBoot 快速实现 api 加密!
03-21
02
SpringBoot整合SQLite
03-07
03
SpringBoot配置使用H2数据库的简单教程
02-21
更多文章>
Theme by Vdoing | Copyright © 2017-2024 | 点击查看十年之约 | 豫ICP备2022014539号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式