结果分组
结果分组将具有公共字段值的文档分组,并返回每个组的顶部文档。
例如,如果您在电子零售商的电子商务网站上搜索“DVD”,您可能会得到三个类别,例如“电视和视频”、“电影”和“计算机”,每个类别有三个结果。在这种情况下,查询词“DVD”出现在所有三个类别中,因此 Solr 将它们分组在一起,以提高用户的相关性。
首选折叠和展开
Solr 的折叠和展开结果功能更新,并且大部分与结果分组重叠。两者都有独特的功能,并且具有不同的性能特征。也就是说,在大多数情况下,折叠和展开优于结果分组。 |
结果分组与分面是分开的。尽管概念上相似,但分面返回所有相关结果,并允许用户根据分面类别细化结果。例如,如果您在鞋类零售商的电子商务网站上搜索“鞋子”,Solr 将返回该查询词的所有结果,以及可选择的分面,例如“尺寸”、“颜色”、“品牌”等等。
但是,您可以将分组与分面结合使用。分组分面支持 facet.field
和 facet.range
,但目前不支持日期和透视分面。分面计数基于第一个 group.field
参数计算,并忽略其他 group.field
参数。
分组分面与非分组分面不同 (所有分面之和) == (具有该属性的产品总数)
,如下例所示
对象 1
-
名称:Phaser 4620a
-
ppm:62
-
product_range:6
对象 2
-
名称:Phaser 4620i
-
ppm:65
-
product_range:6
对象 3
-
名称:ML6512
-
ppm:62
-
product_range:7
如果您要求 Solr 按“product_range”对这些文档进行分组,则组的总数为 2,但 ppm 的分面为 62 的为 2,为 65 的为 1。
分组参数
结果分组采用以下请求参数。可以在单个请求中包含任意数量的这些请求参数
group
-
可选
默认值:
false
如果为
true
,则查询结果将被分组。 group.field
-
可选
默认值:无
用于对结果进行分组的字段的名称。该字段必须是单值字段,并且必须是已索引的字段,或者是具有值源并在函数查询中工作的字段类型,例如
ExternalFileField
。它还必须是基于字符串的字段,例如StrField
或TextField
。 group.func
-
可选
默认值:无
基于函数查询的唯一值进行分组。
此选项不适用于分布式搜索。 group.query
-
可选
默认值:无
返回与给定查询匹配的单个文档组。
rows
-
可选
默认值:
10
返回的组数。
开始
-
可选
默认值:无
指定组列表的初始偏移量。
group.limit
-
可选
默认值:
1
指定每个组要返回的结果数。
group.offset
-
可选
默认值:无
指定每个组的文档列表的初始偏移量。
排序
-
可选
默认值:
score desc
指定 Solr 如何对各组进行相互排序。例如,
sort=popularity desc
将导致各组根据每组中最高受欢迎的文档进行排序。 group.sort
-
可选
默认值:请参阅说明
指定 Solr 如何对每个组内的文档进行排序。如果未指定
group.sort
,则默认行为是使用与sort
参数相同的有效值。 group.format
-
可选
默认值:
grouped
如果此参数设置为
simple
,则分组的文档将以单个平面列表形式呈现,并且start
和rows
参数会影响文档的数量,而不是组的数量。此参数的另一个可选值是grouped
。 group.main
-
可选
默认值:无
如果为
true
,则第一个字段分组命令的结果将用作响应中的主要结果列表,使用group.format=simple
。 group.ngroups
-
可选
默认值:
false
如果为
true
,Solr 会在结果中包含与查询匹配的组数。在使用分片索引时,请参阅下面的分布式结果分组注意事项。
group.truncate
-
可选
默认值:
false
如果为
true
,则分面计数基于与查询匹配的每个组中最相关的文档。 group.facet
-
可选
默认值:
false
确定是否为 facet.field 参数中指定的字段分面计算分组的分面。分组的分面基于第一个指定的分组进行计算。与普通字段分面一样,字段不应被标记化(否则会为每个标记计算计数)。分组分面支持单值和多值字段。
此选项可能会导致严重的性能开销。 在使用分片索引时,请参阅下面的分布式结果分组注意事项。
group.cache.percent
-
可选
默认值:
0
将此参数设置为大于
0
的数字会启用结果分组的缓存。结果分组会执行两次搜索;此选项会缓存第二次搜索。测试表明,组缓存仅在使用布尔、通配符和模糊查询时才能提高搜索速度。对于诸如术语或“匹配所有”查询之类的简单查询,组缓存会降低性能。
可以在单个请求中指定任意数量的组命令(例如,group.field
、group.func
、group.query
等)。
分组示例
以下所有示例查询都适用于 Solr 的“bin/solr start -e techproducts”示例。
按字段分组结果
在此示例中,我们将基于 manu_exact
字段对结果进行分组,该字段指定示例数据集中项目的制造商。
https://127.0.0.1:8983/solr/techproducts/select?fl=id,name&q=solr+memory&group=true&group.field=manu_exact
{
"..."
"grouped":{
"manu_exact":{
"matches":6,
"groups":[{
"groupValue":"Apache Software Foundation",
"doclist":{"numFound":1,"start":0,"docs":[
{
"id":"SOLR1000",
"name":"Solr, the Enterprise Search Server"}]
}},
{
"groupValue":"Corsair Microsystems Inc.",
"doclist":{"numFound":2,"start":0,"docs":[
{
"id":"VS1GB400C3",
"name":"CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail"}]
}},
{
"groupValue":"A-DATA Technology Inc.",
"doclist":{"numFound":1,"start":0,"docs":[
{
"id":"VDBDB1A16",
"name":"A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM"}]
}},
{
"groupValue":"Canon Inc.",
"doclist":{"numFound":1,"start":0,"docs":[
{
"id":"0579B002",
"name":"Canon PIXMA MP500 All-In-One Photo Printer"}]
}},
{
"groupValue":"ASUS Computer Inc.",
"doclist":{"numFound":1,"start":0,"docs":[
{
"id":"EN7800GTX/2DHTV/256M",
"name":"ASUS Extreme N7800GTX/2DHTV (256 MB)"}]
}
}]}}}
响应表明我们的查询共有六个匹配项。对于 group.field
的五个唯一值中的每一个,Solr 返回该 groupValue
的 docList
,使得 numFound
指示该组中的文档总数,并且根据隐含的默认 group.limit=1
和 group.sort=score desc
参数返回顶部文档。然后,根据每个组内顶部文档的分数,基于隐含的 sort=score desc
对结果组进行排序,并且返回的组数限制为隐含的 rows=10
。
我们可以使用请求参数 group.main=true
运行相同的查询。这会将结果格式化为单个平面文档列表。此平面格式不包含与正常结果分组查询结果一样多的信息(特别是每个组中的 numFound
),但对于现有的 Solr 客户端来说,它可能更容易解析。
https://127.0.0.1:8983/solr/techproducts/select?fl=id,name,manufacturer&q=solr+memory&group=true&group.field=manu_exact&group.main=true
{
"responseHeader":{
"status":0,
"QTime":1,
"params":{
"fl":"id,name,manufacturer",
"indent":"true",
"q":"solr memory",
"group.field":"manu_exact",
"group.main":"true",
"group":"true"}},
"grouped":{},
"response":{"numFound":6,"start":0,"docs":[
{
"id":"SOLR1000",
"name":"Solr, the Enterprise Search Server"},
{
"id":"VS1GB400C3",
"name":"CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail"},
{
"id":"VDBDB1A16",
"name":"A-DATA V-Series 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - OEM"},
{
"id":"0579B002",
"name":"Canon PIXMA MP500 All-In-One Photo Printer"},
{
"id":"EN7800GTX/2DHTV/256M",
"name":"ASUS Extreme N7800GTX/2DHTV (256 MB)"}]
}
}
按查询分组
在此示例中,我们将使用 group.query
参数在两个不同的价格范围内查找“memory”的前三个结果:0.00 到 99.99,以及 100 以上。
https://127.0.0.1:8983/solr/techproducts/select?indent=true&fl=name,price&q=memory&group=true&group.query=price:[0+TO+99.99]&group.query=price:[100+TO+*]&group.limit=3
{
"responseHeader":{
"status":0,
"QTime":42,
"params":{
"fl":"name,price",
"indent":"true",
"q":"memory",
"group.limit":"3",
"group.query":["price:[0 TO 99.99]",
"price:[100 TO *]"],
"group":"true"}},
"grouped":{
"price:[0 TO 99.99]":{
"matches":5,
"doclist":{"numFound":1,"start":0,"docs":[
{
"name":"CORSAIR ValueSelect 1GB 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) System Memory - Retail",
"price":74.99}]
}},
"price:[100 TO *]":{
"matches":5,
"doclist":{"numFound":3,"start":0,"docs":[
{
"name":"CORSAIR XMS 2GB (2 x 1GB) 184-Pin DDR SDRAM Unbuffered DDR 400 (PC 3200) Dual Channel Kit System Memory - Retail",
"price":185.0},
{
"name":"Canon PIXMA MP500 All-In-One Photo Printer",
"price":179.99},
{
"name":"ASUS Extreme N7800GTX/2DHTV (256 MB)",
"price":479.95}]
}
}
}
}
在这种情况下,Solr 找到了五个“memory”的匹配项,但仅返回了按价格分组的四个结果。这是因为“memory”的一个结果没有分配价格。
分布式结果分组注意事项
分组支持分布式搜索,但有一些注意事项
-
目前,任何分布式搜索都不支持
group.func
-
group.ngroups
和group.facet
要求每个组中的所有文档必须位于同一分片上,才能返回准确的计数。通过复合键进行文档路由在许多情况下可能是一个有用的解决方案。