Solr的使用 — 檢索

原文:https://www.fanhaobai.com/2017/08/solr-search.html

本文是延續(xù) Solr的使用 系列,前一篇文章已經講了 Solr 的部署和數(shù)據(jù)推送,這里主要以示例方式講述 Solr 的常見查詢語法,同時介紹如何使用 PHP 語言的客戶端 solarium 同 Solr 集群進行數(shù)據(jù)交互。

想要詳細地了解 Solr 查詢語法,可參考 官方wiki。

數(shù)據(jù)格式

用于示例的數(shù)據(jù),我已經推送到了 Solr ,見這里。數(shù)據(jù) Core 為 rooms,數(shù)據(jù)格式形如:

[{
    "resblockId": 1111027377528,
    "resblockName": "金隅麗港城",
    "houseId": 1087599828743,
    "cityCode": 110000,
    "size": 10.5,
    "bizcircleCode": [ 18335711 ],
    "bizcircleName": [ "望京" ],
    "price": 2300,
    "location": "39.997106,116.469306",
    "id": "0119df79-68d9-4cd9-ba07-4d6395a4841c"
},
{
    "resblockId": 1111047349969,
    "resblockName": "融澤嘉園",
    ... ...
}]

查詢語句的組成

通過向 Solr 集群 GET 請求/solr/core-name/select?query形式的查詢 API 完成查詢,其中 core-name 為查詢的 Core 名稱。查詢語句 query 由以下基本元素項組成,按使用頻率先后排序:

名稱 描述 示例
wt 響應結果的格式 json
fl 指定結果集的字段 *(所有字段)
fq 過濾查詢 id : 0119df79-68d9-4cd9-ba07
start 指定結果集起始返回的行數(shù),默認 0 0
rows 指定結果集返回的行數(shù),默認 10 15
sort 結果集的排序規(guī)則 price+asc
defType 設置查詢解析器名稱 dismax
timeAllowed 查詢超時時間

wt

wt 設置結果集格式,支持 json、xml、csv、php、ruby、pthyon,序列化的結果集,常使用 json 格式。

fl

fl 指定返回的字段,多指使用“空格”和“,”號分割,但只支持設置了stored=true的字段。*表示返回全部字段,一般情況不需要返回文檔的全部字段。

字段別名:使用displayName:fieldName形式指定字段的別名,例如:

fl=id,sales_price:price,name

函數(shù):fl 還支持使用 Solr 內置函數(shù),例如根據(jù)單價算總價:

fl=id,total:product(size,price)

fq

fq 過濾查詢條件,可充分利用 cache,所以可以利用 fq 提高檢索性能。

sort

sort 指定結果集的排序規(guī)則,格式為<fieldName>+<sort>,支持 asc 和 desc 兩種排序規(guī)則。例如按照價格倒序排列:

sort=price+desc

也可以多字段排序,價格和面積排序:

sort=price+asc,size+desc

條件查詢

查詢字符串 q 由以下元素項組成,字段條件形如fieldName:value格式:

名稱 描述 示例
q 查詢字符串 :
q.op 表達式之間的關系操作符 AND/OR
df 查詢被索引的字段 id:0119df79-68d9-4cd9-ba07

以上元素項的默認值由solrconfig.xml配置文件定義。通常查詢時設置q=*:*,然后通過 fq 過濾條件來完成查詢,通過緩存提高查詢性能。

模糊查詢

Solr 的模糊查詢使用占位符來描述查詢規(guī)則,如下:

符號 描述 示例
? 匹配單個字符 te?t 會檢索到 test 和 text
* 匹配零個或多個字符 tes* 會檢索到 tes、test 等

查詢小區(qū)名稱中包含“嘉”的房源信息:

-- SQL表述
SELECT * FROM rooms WHERE resblockName LIKE "%嘉%"

Solr 的模糊查詢?yōu)椋?/p>

fq=resblockName:*麗*

單精確值查詢

單精確值查詢是最簡單的查詢,類似于 SQL 中 = 操作符。查詢小區(qū) id 為 1111027377528 的房源信息:

-- SQL表述
SELECT * FROM rooms WHERE resblockId = 1111027377528

Solr 中查詢?yōu)椋?/p>

fq=resblockId:1111027377528

多精確值查詢

多精確值查詢是單精確值查詢的擴展,格式為(value1 value2 ...),功能類似于 SQL 的 IN 操作符。查詢小區(qū) id 為 1111027377528 或者 1111047349969 的房源信息:

-- SQL表述
SELECT * FROM rooms WHERE resblockId IN (1111027377528, 1111047349969)

Solr 中查詢?yōu)椋?/p>

fq=resblockId:(1111027377528 1111047349969)

范圍查詢

范圍查詢是查詢指定范圍的值(數(shù)字和時間),格式為[value1 TO value2],類似于 SQL 的 BETWEEN 操作符。查詢價格在 [2000, 3000] 的房源信息:

-- SQL表述
SELECT * FROM rooms WHERE price BETWEEN 2000 AND 3000

Solr 中范圍查詢?yōu)椋?/p>

fq=price:[2000 TO 3000]

幾個特殊的范圍查詢:

條件 表達式 示例
>= [value TO *] price:[2000 TO *] 價格 >=2000
<= [* TO value] price:[* TO 2000] 價格 <=2000

布爾查詢

將基本查詢結合布爾查詢,就可以實現(xiàn)大部分復雜的檢索場景。布爾查詢支持以下幾種布爾操作:

操作邏輯 操作符 描述
AND &&+ 邏輯與關系
OR 邏輯或關系
NOT !- 邏輯取反關系

查詢北京市價格區(qū)間在 [2000, 3000] 或者上海市價格區(qū)間在 [1500, 2000] 的房源信息:

-- SQL表述
SELECT * FROM rooms WHERE (cityCode=110000 AND price BETWEEN 2000 AND 3000) OR (cityCode=310000 AND price BETWEEN 1500 AND 2000)

轉換為邏輯與布爾查詢:

fq=(cityCode:110000 && price:[2000 TO 3000])||(cityCode:310000 && price:[1500 TO 2000])

Group查詢

在實際中分組查詢比較常見,當然 Solr 也支持分組查詢。分組查詢語句由以下基本元素項組成(常用部分):

名稱 類型 描述
group boolean 是否進行分組查詢
group.field string 按該字段值進行分組
group.limit integer 每組元素集大小,默認為 1
group.offset integer 每組元素起始行數(shù)
group.sort string 組內元素排序規(guī)則,asc 和 desc

查詢西二旗內價格最便宜小區(qū)的房源信息:

-- SQL表述
SELECT * FROM rooms WHERE bizcircleCode=611100314 GROUP BY resblockId ORDER BY price ASC LIMIT 1

Group 分組查詢?yōu)椋?/p>

q=*:*&fq=bizcircleCode:611100314&group=true&group.field=resblockId&group.limit=1&group.sort=size+desc

結果為:

"groups": [
{
    "groupValue": 1111047349969,
    "doclist": {
    "numFound": 1,                 //每組房源數(shù)
    "start": 0,
    "docs": [
    {
        "resblockId": 1111047349969,
        "resblockName": "融澤嘉園",
        "bizcircleCode": [ 611100314 ],
        "price": 2500
        ... ...
    }]
    ... ...
}]

Facet查詢

在大多數(shù)情況下,Group 分組已經能滿足我們的需求,但是如果待分組字段為多值,Group 分組已經無能為力了,這時使用 Facet 就能輕松解決。

Solr 的 Facet 語句由以下基本元素構成(常用):

名稱 類型 描述
facet boolean 是否進行 facet 查詢
facet.field string 按該字段值進行 facet
facet.limit integer 每組元素集大小,默認為 1
facet.offset integer 每組元素起始行數(shù)
facet.sort string 結果集排序規(guī)則,asc 和 desc
facet.mincount integer 每組元素最小數(shù)量

例如,統(tǒng)計每個商圈的房源分布情況并倒序排列,由于 bizcircleCode 字段為多值,F(xiàn)acet 查詢?yōu)椋?/p>

//此時不需要文檔信息,故rows=0
q=*:*&fq=cityCode:110000&facet=true&facet.field=bizcircleCode&facet.sort=desc&rows=0

結果如下:

"facet_fields": {
    "bizcircleCode": [
        "18335711",
        1,
        "18335745",
        1,
        "611100314",
        3
    ]
}

空間檢索

Solr 的 geofilt 過濾器可以實現(xiàn) LBS 檢索,但要在schema.xml配置中將需檢索字段的字段類型設置為solr.LatLonType類型。geofilt 過濾器參數(shù)列表如下:

名稱 描述 示例
d 檢索距離,單位 km 2
pt 檢索中心點坐標,格式:lat,lon 40.074203,116.315445
sfield 檢索的索引字段 location

示例中的 location 字段,值為 “40.074203,116.315445”,類型配置為:

<fieldType name="location" class="solr.LatLonType" subFieldSuffix="_coordinate"/>
<field name="location" type="location"/>

則檢索坐標點40.074203,116.315445附近 2 公里的房源信息:

q=*:*&fq={!geofilt}&spatial=true&pt=40.074203,116.315445&sfield=location&d=2

函數(shù)

Solr 提供一些函數(shù)以實現(xiàn)邏輯或數(shù)學運算。其中常用 數(shù)學運算 函數(shù)列表如下:

函數(shù)名 描述 示例
abs 求絕對值 abs(-5)
max 返回最大值 max(1, 2, 3)
min 返回最小值 min(1, 2, 3)
pow 返回指數(shù)運算的結果 pow(2, 2)
sqrt 開方運算的結果 sqrt(100)
product 乘積 product(1, 2, 3)
sub sub(3, 2)
sum sum(1, 2, 3)
div div(4, 2)
log 10 的對數(shù) log(10)

常用的 邏輯運算 函數(shù):

函數(shù)名 描述 示例
def 定義字段默認值 def(price, 0)
if if(test,value1,value2)test?value1:value2
exists 字段是否存在

這些函數(shù)可以使用在返回值或者查詢條件上。例如返回每個房源的每平方米價格信息:

q=*:*&fl=*,avgPrice:div(price, size)

solarium客戶端

PHP 可以使用 solarium 客戶端,實現(xiàn) Solr 數(shù)據(jù)源的檢索,詳細使用說明 見這里。

配置基本

solarium 客戶端需要配置 Solr 的基本信息。如下:

//config.php
<?php
$solr = [
    'endpoint' => [
        'localhost' => [
            'host' => 'solr.fanhaobai.com',
            'port' => 80,
            'path' => '/solr/rooms/',
        ]
    ]
];

基本查詢

solarium 提供的查詢方法較豐富,整理后如下表所示:

方法 所屬對象 描述
createSelect client 創(chuàng)建查詢 query 對象
select client 執(zhí)行查詢,返回 result 對象
setQuery query 添加 query 條件
setStart query 設置結果集起始行
setRows query 設置結果集行數(shù)
setFields query 設置返回的字段
addSort query 結果集排序規(guī)則
createFilterQuery query 創(chuàng)建 filter query 對象

查詢北京市的所有房源信息,如下:

$client = new Solarium\Client($solr);
$query = $client->createSelect()->setStart(0)->setRows(20);
$query->createFilterQuery('rooms')->setQuery('cityCode:110000');
$result = $client->select($query);

Group查詢

solarium 提供的分組查詢方法如下表所示(常用):

方法 所屬對象 描述
getGrouping query 創(chuàng)建分組 group 對象
addQuery group 添加分組 query
setSort group 設置分組排序規(guī)則
setLimit group 設置分組數(shù)量
getGrouping result 獲取分組信息

獲取西二旗每個小區(qū)的房源分布信息,如下:

$client = new Solarium\Client($solr);
$query = $client->createSelect()->setStart(0)->setRows(20)->setQuery('bizcircleCode:611100314');
$group = $query->getGrouping();
$group->addField('resblockId')->setLimit(10)->setSort('price desc')->setNumberOfGroups(true);
$result = $client->select($query);
$groups = $result->getGrouping();

Facet查詢

solarium 提供的 Facet 查詢方法,如下表(常用):

方法 所屬對象 描述
getFacetSet query 創(chuàng)建分組 facet 對象
createFacetField facet 創(chuàng)建 facet 字段
setField facet facet 分組字段
setLimit facet 設置 facet 分組大小

獲取北京市每個商圈的房源分布信息,如下:

$client = new Solarium\Client($solr);
$query = $client->createSelect()->setStart(0)->setRows(20)->setQuery('bizcircleCode:611100314');
$facet = $query->getFacetSet();
$facet->createFacetField('bizcircle')->setField('bizcircleCode')->setLimit(10);
$result = $client->select($query);

總結

到這里,Solr 系列就整理完畢了,未涉及的部分后續(xù)接觸時再補充。這兩天利用休息時間充電,自己在 Solr 方面的技能也算是上了一個臺階了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容