/FalconEngine

一个go语言实现的简单搜索引擎

Primary LanguageGo

用GO语言实现一个简单的搜索引擎

注意:::::项目完全重构,代码基本完成,还未测试!!!!暂时谨慎直接使用!!README稍后完成全部更新

对搜索引擎感兴趣的可以去看看这本书,比较浅并且也比较完整的介绍了一个搜索引擎的全部机能。

主要功能点,更新列表

  • 类似于数据库的表一样按字段进行存储
  • 支持倒排索引字段,正排索引字段,仅仅储存不进行检索的字段
  • 倒排索引支持
    • 完全匹配的字符串(类似ID,ISBN等需要完全匹配的属性)
    • 分词类型 (全文索引)
    • 根据特殊标志符进行切分的模式
  • 正排索引支持
    • 数字索引(暂时只支持整数,需要自己将其他数转化成整数)
    • 日期索引(目前支持2005-01-02 00:02:032005-01-02两种格式)
    • 不进行检索字段,只存储详细信息
  • 实时搜索引擎,索引器和检索器就是同一个服务,通过json方式push数据进引擎,引擎自行就行存储,不需要先进行全量索引建立
  • 支持搜索,过滤,汇总,统计四种查询
  • 策略引擎部分可以自己实现接口进行扩展
  • 无配置文件,只需要在启动的时候指定端口
  • 使用MMAP方式进行数据存储和读取
  • 使用B+树进行字典和key的存储
  • 实时索引,随时进行索引更新
  • 默认使用文本相关性进行排序
  • 性能测试报告稍后提交

TODO列表

  • 增加选项,可以一次性将所有数据加载进内存
  • 索引分片
  • 分布式部署,保存多个副本
  • 集群化搜索引擎

性能测试

  • 进行中

使用方法

依赖以下几个库


编译

  • 直接运行install.sh
  • bin目录生成FalconEngine 可执行文件

运行

  • 新建data目录,从这里获取分词的字典文件dictionary.txt,存入当前目录的data
  • 新建index文件夹
  • 运行

bin/FalconEngine 【默认端口9990,用 -p=XXX 修改端口】


导入数据

导入数据有三种方式

直接请求导入数据

先建立索引结构
{
    "indexmapping":[
    {
		"fieldname":"datetime",  //字段名称
        "fieldtype":15			 //字段类型
	},     
	{
		"fieldname":"name",
        "fieldtype":2
	},
	{
		"fieldname":"level",
        "fieldtype":1
	},
	{
		"fieldname":"content",
        "fieldtype":2
	}
        ]
}
添加数据
{
    "datetime":"2015-11-12 23:58:22",
    "name":"延参法师",	
    "level":"黄V",
    "content":"看山东,赞山东,和大家一起拉呱,说人生哦。"
}

从文件导入

从文件导入的话,先要建立索引,方法同上
从文件导入

可以把文件存成一行一行的json格式,或者用分隔符分割数据

  • 分隔符分割的文件类似如下
2015-11-12 23:58:22	夢想家林志穎	黄V	加油!!!
2015-11-12 23:58:22	延参法师	黄V	看山东,赞山东,和大家一起拉呱,说人生哦。
2015-11-12 23:58:22	延参法师	黄V	嗯,看时间,潍坊见哦。
2015-11-12 23:58:22	尐笨蛋晴空路口	普通用户	转发微博

然后发送请求:

{
    
    "_split":"\t",  //分隔符
    "_fields":["datetime","name","level","content"], //分隔符对应的字段
    "_filename":"./weibo.log", //文件位置
    "_synccount":200000, 		//多少文档刷新一次磁盘
    "_ismerge":true      		//导入结束后是否将索引合并为一个
}

直接从数据库表导入

直接发送如下格式的POST请求到服务器即可

{
	"sql" : "SELECT user_id,title,author,content,last_modify_time FROM test_table WHERE is_delete=0",  				  //执行的SQL语句,用来获取全量数据
	"user" : "wyh",  				//数据库用户名
	"password" : "wyh", 			//数据库密码
	"host" : "10.254.33.33", 		//数据库地址
	"port" : "3306",				//数据库端口
	"dbname" : "test_DB",			//数据库名称			
	"charset" : "utf8",				//数据库编码
	"tablename" : "test_table",	//需要同步的表名,注意和SQL要一致
	"indexname" : "test_table",	//表对应的搜索引擎索引的名称
	"mapping" : [					//表和索引字段的对应关系
		{
			"field_db":"user_id",
			"field_index" : "user_id",
			"field_type" : 21		//字段类型
			},
		{
			"field_db":"title",
			"field_index" : "title",
			"field_type" : 2
			},
		{
			"field_db":"content",
			"field_index" : "content",
			"field_type" : 2
			},
		{
			"field_db":"author",
			"field_index" : "author",
			"field_type" : 2
			},
		{
			"field_db":"content",
			"field_index" : "content",
			"field_type" : 30
			},
		{
			"field_db":"last_modify_time",
			"field_index" : "last_modify_time",
			"field_type" : 15
			}
	]
}

查询

目前支持GET请求的查询,API如下:

参数 含义 备注
index 索引名称 必须字段
q 查询关键词 q=测试,没有该字段,返回所有结果集
ps 每页数量 ps=10 默认为10
pg 返回第几页 pg=1 默认为1
show 展示字段 show=content,name,level 默认全部字段
gather 汇总字段 gather=level 可选,没填就不汇总
sort 是否排序 sort=false 可选,默认为true,按相关性排序

另外,数字和日期类型的字段可以进行过滤操作,比如有两个字段年龄(age)生日(brith),分别是数字和日期字段,那么可以进行如下过滤操作

操作符号 操作类型 备注
'-' 等于 -age=18&-brith=1990-01-02
'_' 不等于 _age=18&_brith=1990-01-02
'>' 大于 >age=18&>brith=1990-01-02
'<' 小于 <age=18&<brith=1990-01-02
'~' 范围 ~age=16,24&~brith=1990-01-02,2003-03-04

比如上文中的微博的信息

我们要找发布时间在2013-08-18到2015-12-25发布的微博,并且带有关键字雅礼中学的微博,并且还想看看各个级别的人发布了多少条,那么请求就是:

http://127.0.0.1:9990/v1/_search?index=weibo&q=雅礼中学&ps=10&pg=1&show=name,level,datetime,content&~datetime=2013-08-18,2015-12-25&gather=level

返回值为:

{
    "totalCount": 405,          //结果集数量
    "from": 1,                  //此次返回的起始位置
    "to": 10,                   //此次返回的结束位置
    "status": "OK",             //状态
    "costTime": "3.743808ms",   //查询时间
            "Gaters": {         //汇总信息
          "level": {            //level字段汇总
          "付费会员": 11,        //付费会员 有 11 条数据,下同
          "普通用户": 67,
          "蓝V": 84,
          "达人": 14,
          "黄V": 229
          }
	},
"dataDetail": [                 //详情
        {
        "content": "可以回雅礼试试",
        "datetime": "2015-11-12 20:26:27",
        "level": "普通用户",
        "name": "拐栋六R"
        },
        {
        "content": "雅礼中学开始报名了",
        "datetime": "2015-11-12 18:58:03",
        "level": "蓝V",
        "name": "爱尔威智能科技"
        }
  ......
}