solr的facet性能

2019-03-27 01:18|来源: 网路

1.1   facet.method

取值为enum或fc,默认为fc.该字段表示了两种Facet的算法,与执行效率相关.

enum适用于字段值比较少的情况,比如字段类型为布尔型,或者字段表示中国的所有省份.Solr会遍历该字段的所有取值,并从filterCache里为每个值分配一个filter(这里要求solrconfig.xml里对filterCache的设置足够大).然后计算每个filter与主查询的交集.



这里我猜想的计算过程:

首先,对于每个值对应一个filter,类似一个map结构 map<enum,filter>,现在我们假如某一个enum的filter是一个bitset,查询的结果也是一个bitset,那么现在就是计算两个bitset的交集。问题转到求两个bitset的交集的算法上。。。

比如int的最大亿就是2的31次方,用long来存储,要2的25次方长度,那两个位图交集就可以每次取一个long值进行位运算,每次计算的值 就是一个交集数,累加起来就可以得到一个总值 。。



fc(表示Field Cache)适用于字段取值比较多,但在每个文档里出现次数比较少的情况.Solr会遍历所有的文档,在每个文档内搜索Cache内的值,如果找到就将Cache内该值的count加1.


类似视频搜索,



因为分类的值是定的,所以可以采用facet.method=enum.这样,每个分类就对应一个filterCache.只要跟主查询的id进行交集,立即可统计出相应的数量。

试过在几千万的文档,采用facet时,总的费时也是几十毫秒。所以相信用solr来做土豆这个功能也是足以。


这个应该类似sphinx的分层功能。。


可以看看solr的源代码实现,相应也是一种很好的设计方案。。



其它的facet参数:



1.1   facet.prefix

表示Facet字段值的前缀.比如”facet.field=cpu&facet.prefix=Intel”,那么对cpu字段进行Facet查询,返回的cpu都是以”Intel”开头的,”AMD”开头的cpu型号将不会被统计在内.

1.2   facet.sort

表示Facet字段值以哪种顺序返回.可接受的值为true(count)|false(index,lex).true(count)表示按照count值从大到小排列. false(index,lex)表示按照字段值的自然顺序(字母,数字的顺序)排列.默认情况下为true(count).当facet.limit值为负数时,默认facet.sort= false(index,lex).

1.3   facet.limit

限制Facet字段返回的结果条数.默认值为100.如果此值为负数,表示不限制.

1.4   facet.offset

返回结果集的偏移量,默认为0.它与facet.limit配合使用可以达到分页的效果.

1.5   facet.mincount

限制了Facet字段值的最小count,默认为0.合理设置该参数可以将用户的关注点集中在少数比较热门的领域.

1.6   facet.missing

默认为””,如果设置为true或者on,那么将统计那些该Facet字段值为null的记录.

1.7   facet.method

取值为enum或fc,默认为fc.该字段表示了两种Facet的算法,与执行效率相关.

enum适用于字段值比较少的情况,比如字段类型为布尔型,或者字段表示中国的所有省份.Solr会遍历该字段的所有取值,并从filterCache里为每个值分配一个filter(这里要求solrconfig.xml里对filterCache的设置足够大).然后计算每个filter与主查询的交集.

fc(表示Field Cache)适用于字段取值比较多,但在每个文档里出现次数比较少的情况.Solr会遍历所有的文档,在每个文档内搜索Cache内的值,如果找到就将Cache内该值的count加1.

1.8   facet.enum.cache.minDf

当facet.method=enum时,此参数其作用,minDf表示minimum document frequency.也就是文档内出现某个关键字的最少次数.该参数默认值为0.设置该参数可以减少filterCache的内存消耗,但会增加总的查询时间(计算交集的时间增加了).如果设置该值的话,官方文档建议优先尝试25-50内的值.

1.       Date Facet

日期类型的字段在文档中很常见,如商品上市时间,货物出仓时间,书籍上架时间等等.某些情况下需要针对这些字段进行Facet.不过时间字段的取值有无限性,用户往往关心的不是某个时间点而是某个时间段内的查询统计结果. Solr为日期字段提供了更为方便的查询统计方式.当然,字段的类型必须是DateField(或其子类型).

需要注意的是,使用Date Facet时,字段名,起始时间,结束时间,时间间隔这4个参数都必须提供.

与Field Facet类似,Date Facet也可以对多个字段进行Facet.并且针对每个字段都可以单独设置参数.

1.1   facet.date

该参数表示需要进行Date Facet的字段名,与facet.field一样,该参数可以被设置多次,表示对多个字段进行Date Facet.

1.2   facet.date.start

起始时间,时间的一般格式为” 1995-12-31T23:59:59Z”,另外可以使用”NOW”,”YEAR”,”MONTH”等等,具体格式可以参考org.apache.solr.schema. DateField的java doc.

1.3   facet.date.end

结束时间.

1.4   facet.date.gap

时间间隔.如果start为2009-1-1,end为2010-1-1.gap设置为”+1MONTH”表示间隔1个月,那么将会把这段时间划分为12个间隔段.注意”+”因为是特殊字符所以应该用”%2B”代替.

1.5   facet.date.hardend

取值可以为true|false,默认为false.它表示gap迭代到end处采用何种处理.举例说明start为2009-1-1,end为2009-12-25,gap为”+1MONTH”,hardend为false的话最后一个时间段为2009-12-1至2010-1-1;hardend为true的话最后一个时间段为2009-12-1至2009-12-25.

1.6   facet.date.other

取值范围为before|after|between|none|all,默认为none.

before会对start之前的值做统计.

after会对end之后的值做统计.

between会对start至end之间所有值做统计.如果hardend为true的话,那么该值就是各个时间段统计值的和.

none表示该项禁用.

all表示before,after,all都会统计.



转自:http://blog.csdn.net/duck_genuine/article/details/6711590

相关问答

更多
  • commit 有返回值的 UpdateResponse updateResponse = solrServer.commit(); int status = updateResponse.getStatus() 这里的 status 可以拿到操作执行的状态 ,0表示 成功 if (status != 0) { log.error("Some horrible error has occurred, sta...
  • 我无法通过Solr或插件配置找到这样做的方法,所以我开发了一种方法来有效地创建组构面计数,同时仍然使用CollapsingQParserPlugin。 我这样做是通过复制我将要面对的字段并确保整个组的所有方面值都在每个文档中,如下所示: "docs": [ { "id": "1", "workId": "abc", "type": "book", "facetType": [ "book", "ebook" ] }, { " ...
  • 如果您要进行查询 - 请执行查询。 Lucene针对查询进行了高度优化,因此您应该这样做。 facet查询用于从任意查询创建构面(计数) - 因此在内部它执行相同的操作。 如果你生成一个facet然后遍历那个facet,那么Lucene必须查看的文档比你查询单个值时要多得多。 获得性能提升的最佳策略是批量执行这些操作 - 检查同一批次中的500本书(即isbn:(123 OR 321 OR 567 OR 765) ),然后在代码中处理。 如果这些更新可以并行地从许多系统到达,而不需要通过单一来源,那么您必须 ...
  • 如果您期望您的实体经常更改,则更容易索引ID,并且当您得到结果时,请在数据库中查找以获取颜色的名称。 这种方式改变颜色不会要求索引中更新受影响的文档。 在我们的系统中,我们将索引ID的Lucene而不是实体的名称,这正是由于您陈述的原因。 另外,我们的实体有一些与它们相关的属性,这些属性没有编入索引,所以我们必须打开数据库才能获取它们。 就性能而言,ID的面对将不会明显更慢或更快。 就数据库查询而言,这应该不是什么大问题,特别是如果你一次只能拉下数十个方面的话。 如果它成为一个问题,你总是可以使用缓存来加速 ...
  • 您的问题是要按方面值进行过滤。 一个过滤器,它只限制结果列表,但不限制相应的构面字段。 您正在寻找的是标记过滤器查询 : q=my+main+query&fq={!tag=brandTag}brand%3A"Flipkart"&facet=true&facet.field={!ex=brandTag}brand Your question is about to filter by a facet-value. A filter which does only restrict the resultlis ...
  • 将text_path字段定义更改为仅在索引时间应用PathHierarchyTokenizerFactory(以下示例)。 你的问题是你的查询是由标记器处理的,所以fq = libraries:“/ test / subtest”实际上是针对fq =库进行查询的:(/ test / subtest OR / test)。
  • 这是一个已知问题,并且存在一个问题。 请点击https://issues.apache.org/jira/browse/SOLR-6329 也似乎使用minCount = 0处理过多的文档不必要,并使用太多的内存,这可能会解释崩溃的节点。 检查这个jira https://issues.apache.org/jira/browse/SOLR-11711 This is a known issue and there is a issue open for this. check here https://i ...
  • 您可以使用构面查询而不是构面范围来完成所要求的内容。 尝试这样的事情: facet.query=myDateField:[NOW-11MONTH/MONTH TO NOW-10MONTH/MONTH] facet.query=myDateField:[NOW-10MONTH/MONTH TO NOW-9MONTH/MONTH] facet.query=myDateField:[NOW-9MONTH/MONTH TO NOW-8MONTH/MONTH] ... 等等。 现在你可以完全控制任何一个方面, ...
  • 对于过滤器查询,如果未指定该字段,则查询将在默认字段上起作用。 您可以通过添加debugQuery=on来检查执行的过滤器查询 text:solr100 因此,检查默认字段是否应具有CABERNET术语。 此外,匹配将取决于字段类型,执行的分析以及字段索引与否的位置。 只有索引的字段才能过滤结果。 For the filter queries if the field is not speci ...
  • 无法找到合适的解决方案,但猴子修补它像这样: Post.solr_search do facet(:comments_count) do row('No') { with(:comments_count).less_than 1 } row('Yes') { with(:comments_count).greater_than 0 } end case params[:comments_count] when 'No' with(:comments_coun ...