本文是延續(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)階了盯荤。