结果分组
结果分组将具有公共字段值的文档分组到组中,并返回每个组的顶级文档。
例如,如果您在电子零售商的电子商务网站上搜索“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
要返回的组数。
start
-
可选
默认值:无
为组列表指定初始偏移量。
group.limit
-
可选
默认值:
1
为每个组指定要返回的结果数。
group.offset
-
可选
默认值:无
为每个组的文档列表指定初始偏移量。
sort
-
可选
默认值:
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 -e techproducts”示例。
按字段分组结果
在此示例中,我们将根据 manu_exact
字段对结果进行分组,该字段指定示例数据集中的商品制造商。
http://localhost: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 客户端来说可能更容易解析。
http://localhost: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
参数在两个不同的价格范围内找到“内存”的前三个结果:0.00 至 99.99,以及 100 以上。
http://localhost: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 找到了五个与“内存”匹配的结果,但只返回了按价格分组的四个结果。这是因为“内存”的一个结果没有分配价格。
分布式结果分组注意事项
分组受 分布式搜索支持,但有一些注意事项
-
目前
group.func
在任何分布式搜索中都不受支持 -
group.ngroups
和group.facet
要求每个组中的所有文档都必须位于同一分片上,以便返回准确的计数。在许多情况下,通过复合键进行文档路由可能是一个有用的解决方案。