PHP – Solr查询方法

Solr

Solr采用Lucene搜索库为核心,提供全文索引和搜索开源企业平台,提供REST的HTTP/XML和JSON的API。
下载Solr的jar包
执行java -jar start.jar
访问http://localhost:8983/solr/
可以通过java -jar post.jar solr.xml monitor.xml添加文档。
solr.xml



 SOLR1000
 Solr, the Enterprise Search Server
 Apache Software Foundation
 software
 search
 Advanced Full-Text Search Capabilities using Lucene
 Optimized for High Volume Web Traffic
 Standards Based Open Interfaces - XML and HTTP
 Comprehensive HTML Administration Interfaces
 Scalability - Efficient Replication to other Solr Search Servers
 Flexible and Adaptable with XML configuration and Schema
 Good unicode support: héllo (hello with an accent over the e)
 0
 10
 true
 2006-01-17T00:00:00.000Z

数据的处理无外乎增加、删除、修改、查找。
我们来看看怎么操作?

  • 数据导入

可以使用DIH(DataImportHandler)从数据库导入数据
支持CSV文件导入,因此Excel数据也能轻松导入
支持JSON格式文档
二进制文档比如:Word、PDF
还能以编程的方式来自定义导入

  • 更新数据

如果同一份文档solr.xml重复导入会出现什么情况呢?实际上solr会根据文档的字段id来唯一标识文档,如果导入的文档的id已经存在solr中,那么这份文档就被最新导入的同id的文档自动替换。

  • 删除数据

java -Ddata=args -jar post.jar “SOLR1000”
java -Ddata=args -jar post.jar “name:DDR”

  • 查询数据

查询数据都是通过HTTP的GET请求获取的,搜索关键字用参数q指定,另外还可以指定很多可选的参数来控制信息的返回
http://localhost:8983/solr/collection1/select?q=solr&fl=name&wt=json&indent=true
排序:q=video&sort=price desc

全文检索基本原理

首先我们需要知道什么是索引。
想想字典,查一个字,我们用过拼音,比如“翘楚”这个词语,如果我们使用字典顺序扫描的话,需要很久很久,但是如果我们先找到Q对应的位置,然后依次查找,就会很快,这个步骤就是利用了索引的规则,那么字典中的A-Z就是索引,同理,我们处理文本将结果也利用索引的方式存储起来,更加的方便查找。
对于全文检索也是类似的原理,它可以归结为两个过程:1.索引创建(Indexing)2. 搜索索引(Search)。那么索引到底是如何创建的呢?索引里面存放的又是什么东西呢?搜索的的时候又是如何去查找索引的呢?带着这一系列问题继续往下看。

Solr/Lucene采用的是一种反向索引,所谓反向索引:就是从关键字到文档的映射过程,保存这种映射这种信息的索引称为反向索引。

左边保存的是字符串序列
右边是字符串的文档(Document)编号链表,称为倒排表(Posting List)
字段串列表和文档编号链表两者构成了一个字典。现在想搜索”lucene”,那么索引直接告诉我们,包含有”lucene”的文档有:2,3,10,35,92,而无需在整个文档库中逐个查找。如果是想搜既包含”lucene”又包含”solr”的文档,那么与之对应的两个倒排表去交集即可获得:3、10、35、92。

  • 索引创建

假设有如下两个原始文档:
文档一:Students should be allowed to go out with their friends, but not allowed to drink beer.
文档二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

一:把原始文档交给分词组件(Tokenizer)
将文档分成一个一个单独的单词
去除标点符号
去除停词(stop word),所谓停词(Stop word)就是一种语言中没有具体含义,因而大多数情况下不会作为搜索的关键词,这样一来创建索引时能减少索引的大小。英语中停词(Stop word)如:”the”、”a”、”this”,中文有:”的,得”等。不同语种的分词组件(Tokenizer),都有自己的停词(stop word)集合。经过分词(Tokenizer)后得到的结果称为词汇单元(Token)。上例子中,便得到以下词汇单元(Token):
“Students”,”allowed”,”go”,”their”,”friends”,”allowed”,”drink”,”beer”,”My”,”friend”,”Jerry”,”went”,”school”,”see”,”his”,”students”,”found”,”them”,”drunk”,”allowed”

二:词汇单元(Token)传给语言处理组件(Linguistic Processor)
变为小写(Lowercase)
将单词缩减为词根形式,如”cars”到”car”等。这种操作称为:stemming
将单词转变为词根形式,如”drove”到”drive”等。这种操作称为:lemmatization

三:得到的词(Term)传递给索引组件(Indexer)
创建字典

Term    Document ID
student     1
allow       1
go          1
their       1
friend      1
allow       1
drink       1
beer        1
my          2
friend      2
jerry       2
go          2
school      2
see         2
his         2
student     2
find        2
them        2
drink       2
allow       2

对字典按字母顺序排序

Term    Document ID
allow       1
allow       1
allow       2
beer        1
drink       1
drink       2
find        2
friend      1
friend      2
go          1
go          2
his         2
jerry       2
my          2
school      2
see         2
student     1
student     2
their       1
them        2

合并相同的词(Term)成为文档倒排(Posting List)链表

  • 搜索步骤
  • 一:对查询内容进行词法分析、语法分析、语言处理
    词法分析:区分查询内容中单词和关键字,比如:english and janpan,”and”就是关键字,”english”和”janpan”是普通单词
    根据查询语法的语法规则形成一棵树

    语言处理,和创建索引时处理方式是一样的。比如:leaned–>lean,driven–>drive
    二:搜索索引,得到符合语法树的文档集合
    三:根据查询语句与文档的相关性,对结果进行排序
    我们把查询语句也看作是一个文档,对文档与文档之间的相关性(relevance)进行打分(scoring),分数高比较越相关,排名就越靠前。当然还可以人工影响打分,比如百度搜索,就不一定完全按照相关性来排名的。
    如何评判文档之间的相关性?一个文档由多个(或者一个)词(Term)组成,比如:”solr”, “toturial”,不同的词可能重要性不一样,比如solr就比toturial重要,如果一个文档出现了10次toturial,但只出现了一次solr,而另一文档solr出现了4次,toturial出现一次,那么后者很有可能就是我们想要的搜的结果。这就引申出权重(Term weight)的概念。
    权重表示该词在文档中的重要程度,越重要的词当然权重越高,因此在计算文档相关性时影响力就更大。通过词之间的权重得到文档相关性的过程叫做空间向量模型算法(Vector Space Model)
    影响一个词在文档中的重要性主要有两个方面:
    Term Frequencey(tf),Term在此文档中出现的频率,ft越大表示越重要
    Document Frequency(df),表示有多少文档中出现过这个Trem,df越大表示越不重要
    物以希为贵,大家都有的东西,自然就不那么贵重了,只有你专有的东西表示这个东西很珍贵,权重的公式:

    空间向量模型
    文档中词的权重看作一个向量
    Document = {term1, term2, …… ,term N}
    Document Vector = {weight1, weight2, …… ,weight N}
    把欲要查询的语句看作一个简单的文档,也用向量表示:
    Query = {term1, term 2, …… , term N}
    Query Vector = {weight1, weight2, …… , weight N}
    把搜索出的文档向量及查询向量放入N维度的空间中,每个词表示一维:

    夹角越小,表示越相似,相关性越大

    Solr查询串 PHP样例

    $requestArray = array();
    $requestArray['filterList'][0] = ['attribute' => 'webSiteId', "valueArray" => [1, 2, 3]];
    $requestArray['filterList'][1] = ['attribute' => 'sourceType', "valueArray" => [4]];
    $requestArray['minTime']       = $startStamp;
    $requestArray['maxTime']       = $endStamp;
    $keyword = '\"测试\"' OR '\"测试2\"';
    $requestArray['qValue'] = $keyword;
    $requestArray['limit'] = 1000;
    $requestStr = json_encode($requestArray);
    $ret = \SoapService::queryByJson('ARTICLE_URL', ["arg0" => $requestStr, "arg1" =>0, "arg2"=>0]);
    $content = $ret->return;
    

    欢迎留言

    avatar
      Subscribe  
    Notify of