当前位置: 首页 > news >正文

晋江市规划局建设网站数据集网站

晋江市规划局建设网站,数据集网站,wordpress去掉google字体,vi设计可以做哪方面的问题背景 在《搜索引擎关键字智能提示的一种实现》一文中介绍过#xff0c;美团的CRM系统负责管理销售人员的门店(POI)和项目(DEAL)信息#xff0c;提供统一的检索功能#xff0c;其索引层采用的是SolrCloud。在用户搜索时#xff0c;如果能直观地给出每个品类的POI数目美团的CRM系统负责管理销售人员的门店(POI)和项目(DEAL)信息提供统一的检索功能其索引层采用的是SolrCloud。在用户搜索时如果能直观地给出每个品类的POI数目各个状态的DEAL数目可以更好地引导用户进行搜索进而提升搜索体验。 需求分析 例如下图是用户搜索项目(DEAL)的界面当选中一个人或者组织节点后需要实时显示状态分组和快捷分组的每个项的DEAL数目 为了实现上述导航效果可以采用以下两个方案 方案一, 针对每个导航项发送一个Ajax请求去Solr服务器查询对应的DEAL数目。该方案问题在于当导航项比较多时扩展性不好。方案二, 应用Solr自带的Facet技术实现以导航为目的的搜索查询结果根据分类添加count信息。DEAL的Solr索引设计如下 schema.xml field namedeal_id typeint indexedtrue storedtrue / //deal id field nametitle typetext_ika indexedtrue storedfalse / //标题 field namebd_id typeint indexedtrue storedfalse / //负责人id field namebegin_time typelong indexedtrue storedfalse / //项目开始时间 field nameend_time typelong indexedtrue storedfalse / //项目结束时间 field namestatus typeint indexedtrue storedfalse / //项目状态 field namecan_buy typeboolean indexedtrue storedfalse / //是否可以购买 ...省略 本文的例子中用于facet的字段有statuscan_buybegin_timeend_time注 Facet的字段必须被索引无需分词无需存储。无需分词是因为该字段的值代表了一个整体概念无需存储是因为一般而言用户所关心的并不是该字段的具体值而是作为对查询结果进行分组的一种手段用户一般会沿着这个分组进一步深入搜索。 Solr Facet简介 Facet是Solr的高级搜索功能之一Solr作者给出的定义是导航(Guided Navigation)、参数化查询(Paramatic Search)。Facet的主要好处是在搜索的同时可以按照Facet条件进行分组统计给出导航信息改善搜索体验。Facet搜索主要分为以下几类 1. Field Facet 搜索结果按照Facet的字段分组并统计Facet字段通过在请求中加入”facet.field”参数加以声明如果需要对多个字段进行Facet查询那么将该参数声明多次Facet字段必须被索引。例如以下表达式是以DEAL的status和can_buy属性为facet.field进行查询 select?q*:*facettruefacet.fieldstatusfacet.fieldcan_buywtjsonFacet查询需要在请求参数中加入”faceton”或者”facettrue”让Facet组件起作用返回结果 facet_counts”: { facet_queries: {}, facet_fields: { status: [ 32, 96, 0, 40, 8, 81, 16, 50, 127, 80, 64, 27 ] ,can_buy: [ true, 236, false, 21 ]}, facet_dates: {}, facet_ranges: {} }分组count信息包含在“facet_fields”中分别按照”status”和“can_buy”的值分组比如状态为32的DEAL数目有96个能购买的DEAL数目(can_buytrue)是236。 Field Facet主要参数 facet.fieldFacet的字段facet.prefixFacet字段前缀facet.limitFacet字段返回条数facet.offset开始条数偏移量它与facet.limit配合使用可以达到分页的效果facet.mincountFacet字段最小count默认为0facet.missing如果为on或true那么将统计那些Facet字段值为null的记录facet.method取值为enum或fc默认为fcfc表示Field Cachefacet.enum.cache.minDf当facet.methodenum时参数起作用文档内出现某个关键字的最少次数2. Date Facet 日期类型的字段在索引中很常见如DEAL上线时间线下时间等某些情况下需要针对这些字段进行Facet。时间字段的取值有无限性用户往往关心的不是某个时间点而是某个时间段内的查询统计结果Solr为日期字段提供了更为方便的查询统计方式。字段的类型必须是DateField(或其子类型)。需要注意的是使用Date Facet时字段名、起始时间、结束时间、时间间隔这4个参数都必须提供。 与Field Facet类似Date Facet也可以对多个字段进行Facet。并且针对每个字段都可以单独设置参数。 3. Facet Query Facet Query利用类似于filter query的语法提供了更为灵活的Facet。通过facet.query参数可以对任意字段进行筛选。 基于Solr facet的实现 本文的例子需要查询DEAL的“状态”和“快捷选项”导航信息。由于有的状态DEAL数目不仅与状态(status)字段有关还与开始时间(begin_time)和(end_time)相关且各个快捷选项的DEAL数目的计算字段各不相同要求比较灵活的查询所以本文拟采用Facet Query方式实现。 以下代码是采用solrJ构造facet查询对象的过程 public SolrQuery buildFacetQuery(Date now) {SolrQuery solrQuery new SolrQuery();solrQuery.setFacet(true);//设置facetonsolrQuery.setFacetLimit(10);//限制facet返回的数量solrQuery.setQuery(*:*);long nowTime now.getTime() / 1000;long minTime minTimeStamp;long maxTime maxTimeStamp;solrQuery.addFacetQuery(status:0); //待撰写solrQuery.addFacetQuery(status:8); //撰写中solrQuery.addFacetQuery(status:16); //已终审solrQuery.addFacetQuery(status:32 AND begin_time:[ nowTime TO maxTime ]); //已上架-待上线solrQuery.addFacetQuery(status:32 AND begin_time:[ minTime TO nowTime ] AND //已上架-上线中end_time:[ nowTime TO maxTime ]);solrQuery.addFacetQuery(status:32 AND end_time:[ minTime TO nowTime ]); //已上架-已下线return solrQuery; } 说明 “status:0” 查询满足条件的结果集中status0的Deal数目, “status:32 AND “ “begin_time:[” nowTime “ TO ” maxTime “ ]”查询满足条件的结果集中status32且begin_time大于现在时间的Deal数目, 依次类推 返回结果: status:0:756, status:8:28, status:16:21, status:32 AND begin_time:[1401869128 TO 1956499199 ]:4, status:32 AND begin_time:[0 TO 1401869128] AND end_time:[1401869128 TO 1956499199 ]:41, status:32 AND end_time:[0 TO 1401869128]:10}上述结果可知“已上架-待上线”导航项对应的DEAL数为4个。 Solr Facet查询分析 1. Solr HTTP请求分发 当一个Restful(HTTP)查询请求到达SolrCloud服务器首先由SolrDispatchFilter(实现javax.servlet.Filter)处理该类负责分发请求到相应的SolrRequestHandler。具体分发操作在SolrDispatchFilter的doFilter方法中进行 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain, boolean retry) {...... handler core.getRequestHandler( path );if( handler null parser.isHandleSelect() ) {if( /select.equals( path ) || /select/.equals( path ) ) {solrReq parser.parse( core, path, req );String qt solrReq.getParams().get( CommonParams.QT );handler core.getRequestHandler( qt ); //分发到相应的handler.......if( handler ! null ) {...... this.execute( req, handler, solrReq, solrRsp ); //处理请求HttpCacheHeaderUtil.checkHttpCachingVeto(solrRsp, resp, reqMethod); ...... return; }} }protected void execute( HttpServletRequest req, SolrRequestHandler handler, SolrQueryRequest sreq, SolrQueryResponse rsp) {sreq.getContext().put( webapp, req.getContextPath() );sreq.getCore().execute( handler, sreq, rsp ); }接着调用solrCore的execute方法 public void execute(SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) {...... handler.handleRequest(req,rsp); // handler处理请求 postDecorateResponse(handler, req, rsp);...... }从上述代码逻辑可以看出请求的实际处理是由SolrRequestHandler来完成的。 2. SolrRequestHandler处理过程 SolrRequestHandler的类继承结构如下图所示 SolrRequestHandler请求处理器的接口只有两个方法一个是初始化信息主要是配置时的默认参数另一个就是处理请求的接口。 具体处理逻辑主要由SearchHandler类实现。 public interface SolrRequestHandler extends SolrInfoMBean {public void init(NamedList args); //初始化信息public void handleRequest(SolrQueryRequest req, SolrQueryResponse rsp); //处理请求 }SearchHandler实现SolrRequestHandlerSolrCoreAware在SolrCore初始化的过程中调用SolrRequestHandler中的inform(SolrCore core)首先是将solrconfig.xml里配置的各个处理组件按一定顺序组装起来先是first-Component默认的componentlast-component这些处理组件会按照它们的顺序来执行。如果没有配置则加载默认组件方法如下 protected ListString getDefaultComponents() {ArrayListString names new ArrayListString(6);names.add( QueryComponent.COMPONENT_NAME );names.add( FacetComponent.COMPONENT_NAME );names.add( MoreLikeThisComponent.COMPONENT_NAME );names.add( HighlightComponent.COMPONENT_NAME );names.add( StatsComponent.COMPONENT_NAME );names.add( DebugComponent.COMPONENT_NAME );names.add( AnalyticsComponent.COMPONENT_NAME );return names; }SearchHandler中的component对象包含有QueryComponent、FacetComponent、HighlightComponent等其中QueryComponent主要负责查询部分FacetComponent处理facet、HighlightComponent负责高亮显示。SearchHandler在请求处理过程中由SearchHandler.handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp)方法依次调用component的prepare、process、distributedProcess方法(分布式搜索本文暂不讨论) 。QueryComponent调用SolrIndexSearcherSolrIndexSearcher继承了lucene的IndexSearcher类进行搜索FacetComponent实现对Term的层面的统计下图是SearchComponent的类图结构 3. FacetComponent Facet查询分析 由上述分析可知Solr的Facet功能实际上是由FacetComponent组件来实现的具体实现在FacetComponent.process方法中 public void process(ResponseBuilder rb) throws IOException {if (rb.doFacets) {SolrParams params rb.req.getParams();SimpleFacets f new SimpleFacets(rb.req, rb.getResults().docSet,params, rb ); //最终facet查询委托给SimpleFacets类进行处理 NamedListObject counts f.getFacetCounts(); ...... } }首先QueryComponent处理q参数里的查询查询的结果的DocID保存在docSet里这里是一个无序的document ID 的集合。然后把docSet封装在SimpleFacets中调用SimpleFacets.getFacetCounts()获取统计结果 public NamedListObject getFacetCounts() {......facetResponse new SimpleOrderedMapObject();facetResponse.add(facet_queries, getFacetQueryCounts());facetResponse.add(facet_fields, getFacetFieldCounts());facetResponse.add(facet_dates, getFacetDateCounts());facetResponse.add(facet_ranges, getFacetRangeCounts()); ......return facetResponse; }由上可知返回给客户端的结果有四种类型facet_queries、facet_fields、facet_dates、facet_ranges分别调用getFacetQueryCounts()getFacetFieldCounts()getFacetDateCounts()getFacetRangeCounts()完成查询。 4. getFacetQueryCounts统计count过程 由于篇幅原因上述四个方法不一一展开分析本文用到的查询主要是Facet Query下面分析一下getFacetQueryCounts方法源码 public NamedListInteger getFacetQueryCounts() throws IOException,SyntaxError {NamedListInteger res new SimpleOrderedMapInteger();String[] facetQs params.getParams(FacetParams.FACET_QUERY);if (null ! facetQs 0 ! facetQs.length) {for (String q : facetQs) { // 循环统计每个facet query的countparseParams(FacetParams.FACET_QUERY, q);Query qobj QParser.getParser(q, null, req).getQuery();if (qobj null) {res.add(key, 0);} else if (params.getBool(GroupParams.GROUP_FACET, false)) {res.add(key, getGroupedFacetQueryCount(qobj));} else {res.add(key, searcher.numDocs(qobj, docs)); //}}}return res; }该方法的返回类型NamedList是一个有序的name/value容器保存每个facet query和对应的count值。由代码可知在for循环体中逐个统计facet query的count值其中parseParams方法中把”key”设置成本次循环的facet query变量“q“由于GroupParams.GROUP_FACET的值是false(group类似与mysql的group by功能一般不会打开)所以count值实际是由searcher.numDocs(qobj, docs)方法负责计算这里的searcher类型是SolrIndexSearcher。 SolrIndexSearcher的numDocs方法源码如下 public int numDocs(Query a, DocSet b) throws IOException {if (filterCache ! null) { Query absQ QueryUtils.getAbs(a); //如果为negative则返回相应的补集DocSet positiveA getPositiveDocSet(absQ); //查询absQ 获取docSet集合return aabsQ ? b.intersectionSize(positiveA) : b.andNotSize(positiveA);} else {TotalHitCountCollector collector new TotalHitCountCollector();BooleanQuery bq new BooleanQuery();bq.add(QueryUtils.makeQueryable(a), BooleanClause.Occur.MUST);bq.add(new ConstantScoreQuery(b.getTopFilter()), BooleanClause.Occur.MUST);super.search(bq, null, collector);return collector.getTotalHits(); }} 参数a传入facet query对象参数b传入经过QueryComponent组件处理后得到DocSet集合。DocSet存储的是无序的文档标识号(ID)ID并不是我们在schema.xml里配置的unique key而是Solr内部的一个文档标识其次DocSet还封装了集合运算的方法如“求交集”、”求差集”。 由于我们在solrconfig.xml中配置了filterCache filterCache classsolr.FastLRUCache size512 initialSize512 autowarmCount0”/于是numDocs方法中filterCache对象不为null运行到下面三行代码 Query absQ QueryUtils.getAbs(a); //如果为negative则返回相应的补集 DocSet positiveA getPositiveDocSet(absQ); //查询absQ 获取docSet集合 return aabsQ ? b.intersectionSize(positiveA) : b.andNotSize(positiveA); //集合运算首先通过QueryUtils.getAbs(a)将查询对象a统一转化为一个“正向查询对象”absQgetPositiveDocSet(absQ)方法查询absQ对应的DocSet集合getPositiveDocSet方法首先查询filterCache中是否存在absQ查询对象对应的结果存在则直接返回结果否则从索引中查询并把结果保存到filterCache中。 接下来进行集合运算如果Query对象a和absQ是同一个对象表明本次查询是“正向查询”则进行”交集“运算b.intersectionSize(positiveA)否则进行”差集“运算最终返回结果集的size。由此可见facet query对应的count值是集合交集和差集运算后的集合的size。 BTW如果没有用到filterCache会每次都构造一个BooleanQuery查询对象到索引中去查询。 5. FacetComponent Facet排序 Solr的FacetComponet支持两种排序: count和index。count是按每个词出现的次数index是按词的字典顺序。如果查询参数不指定facet.sortSolr默认是按count排序。排序功能是在FacetComponet的finishStage方法中完成的详见源码。 总结 本文介绍了Solr Facet技术并在此基础上实现了DEAL搜索的导航功能然后从源码级别分析了Solr处理Facet请求的详细过程。 参考资料 SimpleFacetParameters http://wiki.apache.org/solr/SimpleFacetParameters使用Apache Lucene和Solr 4实现下一代搜索和分析 http://www.ibm.com/developerworks/cn/java/j-solr-lucene/Faceted Search with Solr http://searchhub.org/2009/09/02/faceted-search-with-solr/
http://www.zqtcl.cn/news/103873/

相关文章:

  • 做ppt配图好用的网站重庆制作网站有哪些
  • 门户网站建设进度安卓手机开发者模式
  • 招商网站建设需要什么网站开发 在线数据库
  • 创建网站代码网站二级页怎么做
  • 网站建设 前沿文章建设网站网站建设公司
  • dede网站seo微信开店怎么注册开店流程
  • 苏华建设集团有限公司网站wordpress 普通文本 quot
  • 网站首页倒计时功能怎么做学网站开发技术
  • 上海网站备案流程欧宇公司网络建设方案
  • 网站营销型办公室装修费用会计分录
  • 个人网站网页设计模板学校ftp服务器做网站
  • 黄江网站建设外贸公司用的采购储运财务软件
  • 优化网站公司做网站建设
  • 门户网站的盈利模式网站建设中备案
  • 代码需求网站织梦怎么关闭网站
  • 浙江工信部网站备案查询东圃做网站
  • icp网站域名怎么填写官方网站建设银行年利息是多少钱
  • 沈阳做网站好的信息流优化师证书
  • 做招聘网站创业seo优化工作
  • 如何维护网站建设外卖网站建设价钱
  • 南宁保洁网站建设乌克兰服装网站建设
  • ppt链接网站怎么做的nas云存储做视频网站
  • 上海网站制作公司联系方式设计素材网站照片
  • 林州网站建设价格网络舆情是什么意思
  • 网站外链平台的建设方法平台类型(至少5个)?兰州道路建设情况网站
  • 网站建立健全举报工作机制设计电子商务网站主页
  • 广州市建设工程交易服务中心网站沈阳百度推广哪家好
  • 个人网站备案需要什么网站建立的重要性
  • wordpress用户名西安seo代理计费
  • 网站建设前准备工作手机上传视频网站开发