搜索基础知识

基本概念

Lucene: Lucene由Doug Cutting开发, Hadoop和Nutch也是出自他之手。
Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上。Lucene 仅仅只是一个库,为了充分发挥其功能,你需要使用 Java 并将 Lucene 直接集成到应用程序中。Elasticsearch 不仅仅是 Lucene,并且也不仅仅只是一个全文搜索引擎。 Elasticsearch可以被下面这样准确的形容:
一个分布式的实时文档存储,每个字段可以被索引与搜索。
一个分布式实时分析搜索引擎。
能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。

Elastic Search基本术语

Index: 名词的时候,是相当于关系型的数据库。

Index: 做动词时索引一个文档 就是存储一个文档到一个 索引 (名词)中以便被检索和查询

Type:  相当于表

Document: 相当于行记录

Doc id:相当于关系型数据的主键

倒排索引:一个倒排索引由文档中所有不重复词的列表构成,对于其中每个词,有一个包含它的文档列表

倒排索引介绍

正向索引如下表

doc idcontents
1quick search for test.
2I am from China.
3Let us go home, China is great

倒排索引如下(分词是基于standard,ES版本是6.8.5):

Term dicPosting IDS
quick1
search1
for1
test1
I2
am2
from3
china2,3
let3
us3
go3
home3
great3


精确搜索

结构化搜索(Structured search) 是指有关探询那些具有内在结构数据的过程。比如日期、时间和数字都是结构化的:它们有精确的格式,我们可以对这些格式进行逻辑操作。比较常见的操作包括比较数字或时间的范围,或判定两个值的大小。

文本也可以是结构化的。比如用户的member type,分为gust,register.

在结构化查询中,我们得到的结果 总是 非是即否,要么存于集合之中,要么存在集合之外。结构化查询不关心文件的相关度或评分;它简单的对文档包括或排除处理。

全文搜索

根据文本搜索文档。比如搜索“ctrip”在不在一段话中。搜索的过程中,首先会涉及到对query分词,query分词后,会根据相关性返回top n的数据。

相关性(Relevance)

它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这种计算方式可以是 TF/IDF 方法、地理位置邻近、模糊相似,或其他的某些算法。

检索词频率

检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。

反向文档频率

每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。

字段长度准则

字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。

分析(Analysis)

它是将文本块转换为有区别的、规范化的 token 的一个过程,(参见 分析的介绍) 目的是为了(a)创建倒排索引以及(b)查询倒排索引。

FST简介

Lucene倒排索引中的核心数据结构是FST。FSA只有状态,FST是在FSA的基础上,增加了输出值. FST构造过程演示:http://examples.mikemccandless.com/fst.py?terms=&cmd=Build+it%21

FST,treeMap,HashMap比较

500万数据,比较的是构建和获取所有key的时间

HashMap      TreeMap  FST    
build(ms)4316        5585      3974    
get all(ms)379          1207      1945    
object size(byte)625554536631999248  768      


HashMap

public void test_HashMap() {
        HashMap<String, Integer> hashMap = new HashMap<>();
        List<String> list = new ArrayList<>();
        for (int i=0; i<5000000; i++) {
            list.add("test"+i+"ab");
        }
        long time1 = System.currentTimeMillis();
        for (int i=0; i<5000000; i++) {
            hashMap.put(list.get(i), i);
        }
        long time2 = System.currentTimeMillis();
        System.out.println("time elapsed for hash map: " + (time2-time1));
        long time3 = System.currentTimeMillis();
        for (int i=0; i<5000000; i++) {
            hashMap.get(list.get(i));
        }
        long time4 = System.currentTimeMillis();
        System.out.println("time elapsed for hash map iterator all: " + (time4-time3));
        long sizeOfType = ObjectSizeCalculator.getObjectSize(hashMap);
        System.out.println("memory occupied for hash map: " + sizeOfType);
    }


TreeMap测试

public void test_TreeMap() {
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        List<String> list = new ArrayList<>();
        for (int i=0; i<5000000; i++) {
            list.add("test"+i+"ab");
        }
        long time1 = System.currentTimeMillis();
        for (int i=0; i<5000000; i++) {
            treeMap.put(list.get(i), i);
        }
        long time2 = System.currentTimeMillis();
        System.out.println("time elapsed for tree map: " + (time2-time1));
        long time3 = System.currentTimeMillis();
        for (int i=0; i<5000000; i++) {
            treeMap.get(list.get(i));
        }
        long time4 = System.currentTimeMillis();
        System.out.println("time elapsed for tree map iterator all: " + (time4-time3));
        long sizeOfType = ObjectSizeCalculator.getObjectSize(treeMap);
        System.out.println("memory occupied for tree map: " + sizeOfType);
    }

FST测试

public void test_FST() {
        try {
            String inputValues[] = new String[5000000];
            Long outputValues[] = new Long[5000000];
            List<String> list = new ArrayList<>();
            for (int i=0;i<5000000; i++) {
                list.add("test"+i+"ab");
            }
            Collections.sort(list);
            for (int i=0; i<5000000; i++) {
                inputValues[i] = list.get(i);
                outputValues[i] = new Long(i+1);
            }
            long time1 = System.currentTimeMillis();
            PositiveIntOutputs outputs = PositiveIntOutputs.getSingleton();
            Builder builder = new Builder(FST.INPUT_TYPE.BYTE1, outputs);
            IntsRefBuilder intsRefBuilder = new IntsRefBuilder();
            for (int i = 0; i < inputValues.length; i++) {
                BytesRef scratchBytes = new BytesRef(inputValues[i]);
                builder.add(Util.toIntsRef(scratchBytes, intsRefBuilder), outputValues[i].longValue());
            }
            FST fst = builder.finish();
            long time2 = System.currentTimeMillis();
            System.out.println("time elapsed for FST: "+(time2-time1));
            long time3 = System.currentTimeMillis();
            for (int i=0; i<5000000; i++) {
                Util.get(fst, new BytesRef(inputValues[i]));
            }
            long time4 = System.currentTimeMillis();
            System.out.println("time elapsed for FST iterator all: "+(time4-time3));
            long sizeOfType = ObjectSizeCalculator.getObjectSize(fst);
            System.out.println("memory occupied for fst: " + sizeOfType);
        } catch (Exception e) {
            ;
        }
    }


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值