Solr的使用 — 檢索

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

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

想要詳細(xì)地了解 Solr 查詢語法慨代,可參考 官方wiki葬项。

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

用于示例的數(shù)據(jù)轻局,我已經(jīng)推送到了 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 請(qǐng)求/solr/core-name/select?query形式的查詢 API 完成查詢暴构,其中 core-name 為查詢的 Core 名稱跪呈。查詢語句 query 由以下基本元素項(xiàng)組成段磨,按使用頻率先后排序:

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

wt

wt 設(shè)置結(jié)果集格式苹支,支持 json、xml误阻、csv债蜜、php枫弟、ruby溯泣、pthyon,序列化的結(jié)果集左医,常使用 json 格式奴紧。

fl

fl 指定返回的字段特姐,多指使用“空格”和“,”號(hào)分割,但只支持設(shè)置了stored=true的字段黍氮。*表示返回全部字段唐含,一般情況不需要返回文檔的全部字段。

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

fl=id,sales_price:price,name

函數(shù):fl 還支持使用 Solr 內(nèi)置函數(shù)捷枯,例如根據(jù)單價(jià)算總價(jià):

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

fq

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

sort

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

sort=price+desc

也可以多字段排序,價(jià)格和面積排序:

sort=price+asc,size+desc

條件查詢

查詢字符串 q 由以下元素項(xiàng)組成拄显,字段條件形如fieldName:value格式:

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

以上元素項(xiàng)的默認(rèn)值由solrconfig.xml配置文件定義苟径。通常查詢時(shí)設(shè)置q=*:*,然后通過 fq 過濾條件來完成查詢躬审,通過緩存提高查詢性能棘街。

模糊查詢

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

符號(hào) 描述 示例
? 匹配單個(gè)字符 te?t 會(huì)檢索到 test 和 text
* 匹配零個(gè)或多個(gè)字符 tes* 會(huì)檢索到 tes承边、test 等

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

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

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

fq=resblockName:*麗*

單精確值查詢

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

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

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

fq=resblockId:1111027377528

多精確值查詢

多精確值查詢是單精確值查詢的擴(kuò)展炒刁,格式為(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ù)字和時(shí)間)翔始,格式為[value1 TO value2]罗心,類似于 SQL 的 BETWEEN 操作符。查詢價(jià)格在 [2000, 3000] 的房源信息:

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

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

fq=price:[2000 TO 3000]

幾個(gè)特殊的范圍查詢:

條件 表達(dá)式 示例
>= [value TO *] price:[2000 TO *] 價(jià)格 >=2000
<= [* TO value] price:[* TO 2000] 價(jià)格 <=2000

布爾查詢

將基本查詢結(jié)合布爾查詢城瞎,就可以實(shí)現(xiàn)大部分復(fù)雜的檢索場(chǎng)景渤闷。布爾查詢支持以下幾種布爾操作:

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

查詢北京市價(jià)格區(qū)間在 [2000, 3000] 或者上海市價(jià)格區(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)

轉(zhuǎn)換為邏輯與布爾查詢:

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

Group查詢

在實(shí)際中分組查詢比較常見脖镀,當(dāng)然 Solr 也支持分組查詢飒箭。分組查詢語句由以下基本元素項(xiàng)組成(常用部分):

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

查詢西二旗內(nèi)價(jià)格最便宜小區(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

結(jié)果為:

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

Facet查詢

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

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

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

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

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

結(jié)果如下:

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

空間檢索

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

名稱 描述 示例
d 檢索距離,單位 km 2
pt 檢索中心點(diǎn)坐標(biāo)伊滋,格式: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"/>

則檢索坐標(biāo)點(diǎn)40.074203,116.315445附近 2 公里的房源信息:

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

函數(shù)

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

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

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

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

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

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

solarium客戶端

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

配置基本

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

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

基本查詢

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

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

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

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

Group查詢

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

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

獲取西二旗每個(gè)小區(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 查詢方法火诸,如下表(常用):

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

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

$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);

總結(jié)

到這里荠察,Solr 系列就整理完畢了置蜀,未涉及的部分后續(xù)接觸時(shí)再補(bǔ)充奈搜。這兩天利用休息時(shí)間充電,自己在 Solr 方面的技能也算是上了一個(gè)臺(tái)階了盯荤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末馋吗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子秋秤,更是在濱河造成了極大的恐慌宏粤,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灼卢,死亡現(xiàn)場(chǎng)離奇詭異绍哎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鞋真,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門崇堰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人灿巧,你說我怎么就攤上這事赶袄。” “怎么了抠藕?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵饿肺,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我盾似,道長(zhǎng)敬辣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任零院,我火速辦了婚禮溉跃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘告抄。我一直安慰自己撰茎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布打洼。 她就那樣靜靜地躺著龄糊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪募疮。 梳的紋絲不亂的頭發(fā)上炫惩,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音阿浓,去河邊找鬼他嚷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的筋蓖。 我是一名探鬼主播卸耘,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼扭勉!你這毒婦竟也來了鹊奖?” 一聲冷哼從身側(cè)響起苛聘,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤涂炎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后设哗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唱捣,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年网梢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了震缭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡战虏,死狀恐怖拣宰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情烦感,我是刑警寧澤巡社,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站手趣,受9級(jí)特大地震影響晌该,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绿渣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一朝群、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧中符,春花似錦姜胖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吧凉,卻和暖如春隧出,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背阀捅。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工胀瞪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓凄诞,卻偏偏與公主長(zhǎng)得像圆雁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帆谍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容