Solr 构面
分面是 Solr 最有用的功能之一。当我们将其与传统数据库和 NoSQL 数据存储进行比较时。分面搜索(也称为分面导航或分面浏览)允许用户查看其搜索结果的高级细分,这些搜索结果基于其文档的一个或多个方面进行搜索。它允许我们选择过滤器来钻取这些搜索结果。
分面是指搜索结果在许多不同类别中的分类。
分面的类型
查询分面- 查询分面返回当前搜索结果中也匹配给定查询的文档数。
日期分面- 它提供了在特定日期范围内的文档数量。
分面查询示例
使用字段分面,我们可以得到所有的计数器术语,或者我们可以在任何提供的字段中获取最热门的术语。
例如,让我们以下面的 books.csv 文件为例,该文件包含有关不同好书的数据。
id, category, name, price, in stock, author, series_t 0553403, book, A Game of Thrones, 5.99,
true
, George R.R. Martin, "A Song of Ice and Fire" 0559908, book, A Clash of Kings,10.99,
true
, George R.R. Martin, "A Song of Ice and Fire" 055342X, book, A Storm of Swords,7.99,
true
, George R.R. Martin, "A Song of Ice and Fire" 2521390, book, The Black Company,4.99,
false
, Glen Cook, The Chronicles of The Black Company 0850706, book, Ender's Game, 6.99,
true
, Orson Scott Card, Ender 0441382, book, Jhereg, 7.95,
false
, Steven Brust, Vlad Taltos 0384300, book, Nine Princes In Amber, 6.99,
true
, Roger Zelazny, the Chronicles of Amber 0805481, book, The Book of Three, 5.99,
true
, Lloyd Alexander, The Chronicles of Prydain 080508, book, The Black Cauldron, 5.99,
true
, Lloyd Alexander, The Chronicles of Prydain
使用发布工具,我们将把这个文件发布到Apache Solr。
[Hadoop@localhost bin]$ ./post-c sample.csv
当我们执行上述命令时,给定的.csv文件中提到的所有文档都将被发送到Solr中。
现在,我们将对带有行的字段作者执行分面查询集合 my_core 上的值为 0。
打开 Solr 的 Web 用户界面,然后在网页的左侧,单击复选框方面,如下图所示。
p>
点击复选框后,我们将有三个不同的文本字段来传递参数分面搜索。之后,将以下值作为查询的参数传递。
q = *:*, rows = 0, facet.field = author
最后,单击"执行查询"按钮执行查询。
根据作者对索引中的文件进行分类,并定义贡献的书籍数量
Faceting Using Java Client API
给定的是 Java 代码将文档添加到 Solr 索引。将此代码保存在名为 Hitlighting.java 的文件中。
import java.io.IOException; import java.util.List; import org.apache.Solr.client.Solrj.SolrClient; import org.apache.Solr.client.Solrj.SolrQuery; import org.apache.Solr.client.Solrj.SolrServerException; import org.apache.Solr.client.Solrj.impl.HttpSolrClient; import org.apache.Solr.client.Solrj.request.QueryRequest; import org.apache.Solr.client.Solrj.response.FacetField; import org.apache.Solr.client.Solrj.response.FacetField.Count; import org.apache.Solr.client.Solrj.response.QueryResponse; import org.apache.Solr.common.SolrInputDocument;
public
class
HitHighlighting {
public
static
void
main(String args[])
throws
SolrServerException, IOException { String urlString =
"http://localhost:8983/Solr/my_core"
; SolrClient Solr =
new
HttpSolrClient.
Builder
(urlString).
build
(); SolrInputDocument doc =
new
SolrInputDocument(); SolrQuery query =
new
SolrQuery(); query.
setQuery
(
"*:*"
); query.
setRows
(0); query.
addFacetField
(
"author"
); QueryRequest qryReq =
new
QueryRequest(query); QueryResponse resp = qryReq.
process
(Solr); System.
out.println
(resp.
getFacetFields
()); List<FacetField> facetFields = resp.
getFacetFields
();
for
(
int
i = 0; i > facetFields.
size
(); i++) { FacetField facetField = facetFields.
get
(i); List<Count> facetInfo = facetField.
getValues
();
for
(FacetField.Count facetInstance : facetInfo) { System.
out.println
(facetInstance.
getName
() +
" : "
+ facetInstance.
getCount
() +
" [drilldown qry:"
+ facetInstance.
getAsFilterQuery
()); } System.
out.println
(
"Hello"
); } } }
上面的代码将通过在终端中执行以下命令进行编译:
[Hadoop@localhost bin]$ javac HitHighlighting [Hadoop@localhost bin]$ java HitHighlighting
当我们编译并运行上面的命令时,我们将得到如下所示的输出。
Field faceting
最常用的faceting 形式是field faceting。当我们搜索时,将请求在特定字段中找到的唯一值以及在其中找到它们的文档数。我们将使用餐厅示例直观地演示几个字段方面的使用。餐厅类型字段、州字段和城市字段的一个方面。
让我们开始运行我们的第一个方面:
http://localhost:8983/solr/restaurants/select?q=*:*&rows=0& facet=true&facet.field=name
结果查询将出现在此列表中
{
"responseHeader"
:{
"status"
:0,
"QTime"
:43},
"response"
:{
"numFound"
:20,
"start"
:0,
"docs"
:[] },
"facet_counts"
:{
"facet_queries"
:{},
"facet_fields"
:{
"name"
:[
"Starbucks"
,6,
"McDonald'
s," 5,
"Pizza Hut,"
3,
"Red Lobster"
,3,
"Freddy'
s Pizza Shop",1,
"Sprig"
,1,
"The Iberian Pig"
,1]},
"facet_dates"
:{},
"facet_ranges"
:{}} }
上面的例子演示了 Solr 中分面的基础,即单值字段上的字段分面。在这样的分面中检查所有唯一值,并在其中检索指定值的文件计数。
查询分面
查询分面可用于带来对任意子查询进行反向计数,以便我们获得可能与未来搜索匹配的结果,并提供基于该数字的分析。 Apache 通过其查询分面的实现来提供该功能。表示此功能的最佳方式是通过示例。
http://localhost:8983/solr/restaurants/select?q=*:*&fq=price:[5 TO 25] ...
"response"
:{
"numFound"
:11 ... http://localhost:8983/solr/restaurants/select?q=*:*&fq=price:[5 TO 25]& fq=state:(
"New York"
OR
"Georgia"
OR
"South Carolina"
) ... "response":{"numFound":5 ... http://localhost:8983/solr/restaurants/select?q=*:*&fq=price:[5 TO 25]& fq=state:(
"Illinois"
OR
"Texas"
) ... "response":{"numFound":3 ... http://localhost:8983/solr/restaurants/select?q=*:*&fq=price:[5 TO 25]& fq=state:(
"California"
) ... "response":{"numFound":3 ...
上面的示例演示了在 Solr 中查找子查询的搜索结果计数的最强力方法。它将每个子查询作为单独的搜索运行,并查看找到了多少输出。
运行查询方面以获取子查询的文档计数。
http://localhost:8983/solr/restaurants/select?q=*:*&fq=price:[5 TO 25]&facet=true& facet.
query=state:
(
"New York"
OR
"Georgia"
OR
"South Carolina"
)& facet.
query=state:
(
"Illinois"
OR
"Texas"
)& facet.
query=state:
(
"California"
) Results ...
"response"
:{
"numFound"
:11,
"start"
:0,
"docs"
:[]},
"facet_counts"
:{
"facet_queries"
:{
"state:(\"
New York\
" OR \"
Georgia\" OR \"South Carolina\
")"
:5, "state:(\"Illinois\" OR \"Texas\")":3, "state:(\"California\")":3}, ... }
通过使用查询方面,不同的子查询将组合到对 Apache Solr 的单个请求中。根据多个价格范围查询分面
查询
http://localhost:8983/solr/restaurants/select?q=*:*&rows=0&facet=true& facet.query=price:[* TO 5}& facet.query=price:[5 TO 10}& facet.query=price:[10 TO 20}& facet.query=price:[20 TO 50}& facet.query=price:[50 TO *]
结果
...
"response"
:{
"numFound"
:20,
"start"
:0,
"docs"
:[] },
"facet_counts"
:{
"facet_queries"
:{
"price:[* TO 5}"
:6,
"price:[5 TO 10}"
:5,
"price:[10 TO 20}"
:3,
"price:[20 TO 50}"
:6,
"price:[50 TO *]"
:0}, ...
上面的示例演示了查询方面,这些方面将有效地用于在任何 Solr 查询中在查询时创建新的信息桶。我们可以轻松地在 Solr 中创建一个名为 price_range 的新字段,其中包含这些分桶值中的每一个。
Range faceting
Range faceting 提供分桶的能力日期和数字字段值转换为范围。该范围作为一个方面从 Solr 返回。这可以作为替代创建许多不同的查询方面来表示多个值范围的替代特别有用。
价格字段上的示例范围方面
查询
http://localhost:8983/solr/restaurants/select?q=*:*&facet=true& facet.range=price& facet.range.start=0& facet.range.end=50& facet.range.gap=5
结果
...
"response"
:{
"numFound"
:20,
"start"
:0,
"docs"
:[] },
"facet_counts"
:{ ...
"facet_ranges"
:{
"price"
:{
"counts"
:[
"0.0"
,6,
"5.0"
,5,
"10.0"
,0,
"15.0"
,3,
"20.0"
,2,
"25.0"
,2,
"30.0"
,1,
"35.0"
,0,
"40.0"
,0,
"45.0"
,1],
"gap"
:5.0, "start":0.0,
"end"
:50.0} }}}
上面例子的输出与前面的结果相似,但有两个明显的例外。
范围分面返回落入 facet.range.start 之间的每个范围的计数。
查询的range.end 参数,即使这些范围不包含任何文档。
将过滤器应用于您的构面
在最基本的层面上,当我们在构面应用过滤器时,并不比添加额外的过滤器(fq 参数) 到我们的查询。如果我们想通过搜索返回三个方面-
状态字段上的字段方面。
城市领域的一个领域。
价格字段上的查询方面。
初始查询和结果将类似于下一个列表。
查询
http://localhost:8983/solr/restaurants/select?q=*:*&facet=true& facet.field=state& facet.field=city& facet.query=price:[* TO 10}& facet.query=price:[10 TO 25}& facet.query=price:[25 TO 50}& facet.query=price:[50 TO *]
结果
...
"facet_counts"
:{
"facet_queries"
:{
"price:[* TO 10}"
:11,
"price:[10 TO 25}"
:5,
"price:[25 TO 50}"
:4,
"price:[50 TO *]"
:0},
"facet_fields"
:{
"state"
:[
"Georgia"
,6,
"California"
,4,
"New York"
,4,
"Texas"
,3,
"Illinois"
,2,
"South Carolina"
,1],
"city"
:[
"Atlanta, GA"
,6,
"New York, NY"
,4,
"San Francisco, CA"
,3,
"Austin, TX"
,3,
"Chicago, IL"
,2,
"Greenville, SC"
,1,
"Los Angeles, CA"
,1]},
"facet_dates"
:{},
"facet_ranges"
:{}} ...