浏览代码

HUE-1742 [search] Improve graphical facet performances

Added possibility to specify range specific data
Fixed icons on templates
Limited returned facets to 100
Enrico Berti 12 年之前
父节点
当前提交
f6db605

+ 32 - 19
apps/search/src/search/models.py

@@ -62,10 +62,10 @@ class Facet(models.Model):
     properties = data_dict.get('properties')
 
     params = (
-        ('facet', properties.get('isEnabled') and 'true' or 'false'),
-        ('facet.mincount', properties.get('mincount')),
-        ('facet.limit', -1),
-        ('facet.sort', properties.get('sort')),
+      ('facet', properties.get('isEnabled') and 'true' or 'false'),
+      ('facet.mincount', properties.get('mincount')),
+      ('facet.limit', 100),
+      ('facet.sort', properties.get('sort')),
     )
 
     if data_dict.get('fields'):
@@ -73,17 +73,31 @@ class Facet(models.Model):
       params += field_facets
 
     if data_dict.get('charts'):
-      field_facets = tuple([('facet.field', field_facet['field']) for field_facet in data_dict['charts']])
-      params += field_facets
+      for field_facet in data_dict['charts']:
+        if field_facet['start'] and field_facet['end'] and field_facet['gap']:
+          range_facets = tuple([
+             ('facet.range', field_facet['field']),
+             ('f.%s.facet.limit' % field_facet['field'], -1),
+             ('f.%s.facet.range.start' % field_facet['field'], field_facet['start']),
+             ('f.%s.facet.range.end' % field_facet['field'], field_facet['end']),
+             ('f.%s.facet.range.gap' % field_facet['field'], field_facet['gap']),]
+          )
+          params += range_facets
+        else:
+          field_facets = tuple([
+            ('facet.field', field_facet['field']),
+            ('f.%s.facet.limit' % field_facet['field'], -1),
+          ])
+          params += field_facets
 
     if data_dict.get('ranges'):
       for field_facet in data_dict['ranges']:
         range_facets = tuple([
-                           ('facet.range', field_facet['field']),
-                           ('f.%s.facet.range.start' % field_facet['field'], field_facet['start']),
-                           ('f.%s.facet.range.end' % field_facet['field'], field_facet['end']),
-                           ('f.%s.facet.range.gap' % field_facet['field'], field_facet['gap']),]
-                        )
+           ('facet.range', field_facet['field']),
+           ('f.%s.facet.range.start' % field_facet['field'], field_facet['start']),
+           ('f.%s.facet.range.end' % field_facet['field'], field_facet['end']),
+           ('f.%s.facet.range.gap' % field_facet['field'], field_facet['gap']),]
+        )
         params += range_facets
 
     if data_dict.get('dates'):
@@ -93,12 +107,11 @@ class Facet(models.Model):
         gap = field_facet['gap']
 
         date_facets = tuple([
-                           ('facet.date', field_facet['field']),
-                           ('f.%s.facet.date.start' % field_facet['field'], 'NOW-%(frequency)s%(unit)s/%(rounder)s' % {"frequency": start["frequency"], "unit": start["unit"], "rounder": gap["unit"]}),
-                           ('f.%s.facet.date.end' % field_facet['field'], 'NOW-%(frequency)s%(unit)s' % end),
-                           ('f.%s.facet.date.gap' % field_facet['field'], '+%(frequency)s%(unit)s' % gap),]
-                        )
-
+           ('facet.date', field_facet['field']),
+           ('f.%s.facet.date.start' % field_facet['field'], 'NOW-%(frequency)s%(unit)s/%(rounder)s' % {"frequency": start["frequency"], "unit": start["unit"], "rounder": gap["unit"]}),
+           ('f.%s.facet.date.end' % field_facet['field'], 'NOW-%(frequency)s%(unit)s' % end),
+           ('f.%s.facet.date.gap' % field_facet['field'], '+%(frequency)s%(unit)s' % gap),]
+        )
         params += date_facets
 
     return params
@@ -358,7 +371,7 @@ def augment_solr_response(response, facets):
       for cat in response['facet_counts']['facet_fields']:
         facet = {
           'field': cat,
-          'type': is_chart_field(cat, chart_facets) and 'chart' or 'field',
+          'type': 'chart' if is_chart_field(cat, chart_facets) else 'field',
           'label': get_facet_field_label(cat, is_chart_field(cat, chart_facets) and 'chart' or 'field', facets),
           'counts': response['facet_counts']['facet_fields'][cat],
         }
@@ -372,7 +385,7 @@ def augment_solr_response(response, facets):
       for cat in response['facet_counts']['facet_ranges']:
         facet = {
           'field': cat,
-          'type': 'range',
+          'type': 'chart' if is_chart_field(cat, chart_facets) else 'range',
           'label': get_facet_field_label(cat, 'range', facets),
           'counts': response['facet_counts']['facet_ranges'][cat]['counts'],
           'start': response['facet_counts']['facet_ranges'][cat]['start'],

+ 64 - 27
apps/search/src/search/templates/admin_collection_facets.mako

@@ -189,30 +189,43 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
         </div>
       </div>
 
-        <div id="step5" class="stepDetails hide">
-          <div data-bind="visible: chartFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
-            <em>${_('There is currently no graphical facet defined. Remember, you can add just one field as graphical facet.')}</em>
-          </div>
-          <div data-bind="foreach: chartFacets">
-            <div class="bubble">
-              <strong><span data-bind="editable: label"></span></strong>
-              <span style="color:#666;font-size: 12px">(<span data-bind="text: field"></span>)</span>
-              <a class="btn btn-small" data-bind="click: $root.removeChartFacet"><i class="fa fa-trash-o"></i></a>
-            </div>
-          </div>
-          <div class="clearfix"></div>
-          <div class="miniform">
-            ${_('Field')}
-            <select id="select-chart-facet" data-bind="options: chartFacetsList, value: selectedChartFacet"></select>
-            &nbsp;${_('Label')}
-            <input id="selectedChartLabel" type="text" data-bind="value: selectedChartLabel" class="input" />
-            <br/>
-            <br/>
-            <a class="btn" data-bind="click: $root.addChartFacet, css:{disabled: $root.chartFacets().length == 1}"><i class="fa fa-plus-circle"></i> ${_('Set as Graphical Facet')}</a>
-            &nbsp;<span id="chart-facet-error" class="label label-important hide">${_('You can add just one field as graphical facet')}</span>
-            <span id="chart-facet-error-wrong-field-type" class="label label-important hide">${_('You can add just one field as graphical facet')}</span>
+      <div id="step5" class="stepDetails hide">
+        <div data-bind="visible: chartFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
+          <em>${_('There is currently no graphical facet defined. Remember, you can add just one field as graphical facet.')}</em>
+        </div>
+        <div data-bind="foreach: chartFacets">
+          <div class="bubble">
+            <strong><span data-bind="editable: label"></span></strong>
+            <span style="color:#666;font-size: 12px">
+              (<span data-bind="text: field"></span>, <span data-bind="editable: start"></span> <i class="fa fa-double-angle-right"></i> <span data-bind="editable: end"></span>,
+              <i class="fa fa-resize-horizontal"></i> <span data-bind="editable: gap"></span>)
+            </span>
+            <a class="btn btn-small" data-bind="click: $root.removeChartFacet"><i class="fa fa-trash-o"></i></a>
           </div>
         </div>
+        <div class="clearfix"></div>
+        <div class="miniform">
+          ${_('Field')}
+          <select id="select-chart-facet" data-bind="options: chartFacetsList, value: selectedChartFacet"></select>
+          &nbsp;${_('Label')}
+          <input id="selectedChartLabel" type="text" data-bind="value: selectedChartLabel" class="input" />
+          <br/>
+          <br/>
+          ${_('Start')}
+          <input type="number" data-bind="value: selectedChartStartFacet" class="input-medium" />
+          &nbsp;${_('End')}
+          <input type="number" data-bind="value: selectedChartEndFacet" class="input-medium" />
+          &nbsp;${_('Gap')}
+          <input type="number" data-bind="value: selectedChartGapFacet" class="input-mini" />
+          <span id="chart-facet-help-general"  class="muted">&nbsp;${_('If empty this will be treated as a simple Field Facet.')}</span>
+          <span id="chart-facet-help-date" class="muted hide">&nbsp;${_('You can use fixed dates or functions. ie. Start: NOW-12HOURS/MINUTES, End: NOW, Gap: +30MINUTES')}</span>
+          <br/>
+          <br/>
+          <a class="btn" data-bind="click: $root.addChartFacet, css:{disabled: $root.chartFacets().length == 1}"><i class="fa fa-plus-circle"></i> ${_('Set as Graphical Facet')}</a>
+          &nbsp;<span id="chart-facet-error" class="label label-important hide">${_('You can add just one field as graphical facet')}</span>
+          <span id="chart-facet-error-wrong-field-type" class="label label-important hide">${_('You can add just one field as graphical facet')}</span>
+        </div>
+      </div>
 
       <div id="step6" class="stepDetails hide">
         <div data-bind="visible: sortableFacets().length == 0" style="padding-left: 10px;margin-bottom: 20px">
@@ -593,7 +606,7 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
   }
 
   var ChartFacet = function (obj) {
-    return new Facet({type: "chart", field: obj.field, label: obj.label, uuid: obj.uuid});
+    return new Facet({type: "chart", field: obj.field, label: obj.label, start: obj.start, end: obj.end, gap: obj.gap, uuid: obj.uuid});
   }
 
   var RangeFacet = function (obj) {
@@ -702,10 +715,12 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
       return new ChartFacet(obj);
     }));
 
-    // Remove already selected fields
-    self.chartFacetsList = ko.observableArray(${ hue_collection.fields(user) | n,unicode });
-    $.each(self.chartFacets(), function(index, field) {
-      self.chartFacetsList.remove(field.field);
+    // Only dates and numbers
+    self.chartFacetsList = ko.observableArray([]);
+    $.each(self.fields(), function(index, field) {
+      if (self.fullFields[field] && ['tdate', 'date', 'tint', 'int', 'tlong', 'long'].indexOf(self.fullFields[field].type) >= 0) {
+        self.chartFacetsList.push(field);
+      }
     });
 
     // List of all facets sorted by UUID
@@ -746,9 +761,21 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
 
     self.selectedChartFacet = ko.observable();
     self.selectedChartFacet.subscribe(function (newValue) {
+      var _field = self.fullFields[newValue];
+      if (_field.type == "tdate"){
+        $("#chart-facet-help-date").removeClass("hide");
+        $("#chart-facet-help-general").addClass("hide");
+      }
+      else {
+        $("#chart-facet-help-date").addClass("hide");
+        $("#chart-facet-help-general").removeClass("hide");
+      }
       $("#selectedChartLabel").prop("placeholder", newValue);
     });
     self.selectedChartLabel = ko.observable("");
+    self.selectedChartStartFacet = ko.observable("");
+    self.selectedChartEndFacet = ko.observable("");
+    self.selectedChartGapFacet = ko.observable("");
 
 
     self.removeFieldFacet = function (facet) {
@@ -874,8 +901,18 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
             self.selectedChartLabel(self.selectedChartFacet());
           }
           var newFacet = new ChartFacet({field: self.selectedChartFacet(), label: self.selectedChartLabel()});
+          var newFacet = new ChartFacet({
+            field: self.selectedChartFacet(),
+            label: self.selectedChartLabel(),
+            start: self.selectedChartStartFacet(),
+            end: self.selectedChartEndFacet(),
+            gap: self.selectedChartGapFacet()
+         });
           self.chartFacets.push(newFacet);
           self.selectedChartLabel("");
+          self.selectedChartStartFacet("");
+          self.selectedChartEndFacet("");
+          self.selectedChartGapFacet("");
           self.chartFacetsList.remove(self.selectedChartFacet());
           self.properties().isEnabled(true);
           self.isSaveBtnVisible(true);

+ 22 - 6
apps/search/src/search/templates/search.mako

@@ -142,7 +142,7 @@ ${ commonheader(_('Search'), "search", user, "90px") | n,unicode }
                 remove_list.remove(fq)
             %>
             % for group, count in macros.pairwise(fld['counts']):
-              % if count > 0 and group != "" and found_value == "":
+              % if count > 0 and group != "" and found_value == "" and loop.index < 100:
                 % if fld['type'] == 'field':
                   <li class="facetItem"><a href='?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${ solr_query['fq'] }|${ fld['field'] }:"${ urllib.quote_plus(group.encode('ascii', 'xmlcharrefreplace')) }"${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}'>${group}</a> <span class="counter">(${ count })</span></li>
                 % endif
@@ -153,7 +153,7 @@ ${ commonheader(_('Search'), "search", user, "90px") | n,unicode }
                   <li class="facetItem dateFacetItem"><a href='?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${ solr_query['fq'] }|${ fld['field'] }:[${ group } TO ${ group }${ urllib.quote_plus(fld['gap']) }]${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}'><span class="dateFacet" data-format="${fld['format']}">${ group }<span class="dateFacetGap hide">${ fld['gap'] }</span></span></a> <span class="counter">(${ count })</span></li>
                 % endif
               % endif
-              % if found_value != "":
+              % if found_value != "" and loop.index < 100:
                 % if fld['type'] == 'field' and '"' + group + '"' == found_value:
                   <li class="facetItem"><strong>${ group }</strong> <a href="?collection=${ current_collection }&query=${ solr_query['q'] }&fq=${'|'.join(remove_list)}${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}"><i class="fa fa-times"></i></a></li>
                 % endif
@@ -202,7 +202,7 @@ ${ commonheader(_('Search'), "search", user, "90px") | n,unicode }
             for group, count in macros.pairwise(fld['counts']):
               values += "['" + group + "'," + str(count) + "],"
           %>
-          <div class="chartComponent" data-values="[${values[:-1]}]" data-label="${fld['label']}" data-field="${fld['field']}">
+          <div class="chartComponent" data-values="[${values[:-1]}]" data-label="${fld['label']}" data-field="${fld['field']}" data-gap="${'gap' in fld and fld['gap'] or ''}">
             <!--[if lte IE 9]>
               <img src="/static/art/spinner-big.gif" />
             <![endif]-->
@@ -340,7 +340,7 @@ ${ commonheader(_('Search'), "search", user, "90px") | n,unicode }
         $(section).hide();
       }
       if (_showMore){
-        $("<li>").addClass("facetShowMore").html('<a href="javascript:void(0)">${_('More...')}</a>').insertAfter(_lastSection);
+        $("<li>").addClass("facetShowMore").html('<a href="javascript:void(0)">${_('Show')} ' + ($(section).nextUntil(".facetHeader").length-(collectionProperties.limit*1)) + ' ${_('more...')}</a>').insertAfter(_lastSection);
       }
     });
 
@@ -557,9 +557,25 @@ ${ commonheader(_('Search'), "search", user, "90px") | n,unicode }
                 $(".chartComponent").data("plotObj").highlight(item.series, item.datapoint);
                 var _point = item.datapoint[0];
                 if (_isDate){
-                  _point = '"' + moment(item.datapoint[0]).utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]") + '"';
+                  var _momentDate = moment(item.datapoint[0]);
+                  var _gap = $(".chartComponent").data("gap");
+                  if (_gap != null && _gap != ""){
+                    var _futureMomentDate = moment(item.datapoint[0]);
+                    var _how = _gap.match(/\d+/)[0];
+                    var _what = _gap.substring(_how.length + 1).toLowerCase();
+                    _futureMomentDate.add(_what, _how * 1);
+                    var _start = _momentDate.utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]");
+                    var _end = _futureMomentDate.utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]");
+                    location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':["' + _start + '" TO "' + _end + '"]') + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
+                  }
+                  else {
+                    _point = '"' + _momentDate.utc().format("YYYY-MM-DD[T]HH:mm:ss[Z]") + '"';
+                    location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':' + _point) + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
+                  }
+                }
+                else {
+                  location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':' + _point) + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
                 }
-                location.href = '?collection=${ current_collection }&query=${ solr_query['q'] }&fq=' + getFq("${ solr_query['fq'] }", $(".chartComponent").data("field"), ':' + _point) + '${solr_query.get("sort") and '&sort=' + solr_query.get("sort") or ''}';
               }
             }
           });

+ 3 - 3
apps/search/static/templates/templates.xml

@@ -13,7 +13,7 @@
       </div>
       <div class="span11">
         <a href="https://twitter.com/{{user_screen_name}}/status/{{id}}" class="btn openTweet">
-          <i class="icon-twitter"></i>
+          <i class="fa fa-twitter"></i>
         </a>
         <b>{{user_name}}</b>
         <br/>
@@ -107,10 +107,10 @@ em {
     $(".stars").each(function(){
   	  var _h = "";
   	  for (var i=0;i<$(this).data("stars")*1;i++){
-        _h += '<i class="icon-star"></i>';
+        _h += '<i class="fa fa-star"></i>';
   	  }
   	  for (var i=$(this).data("stars")*1;i<5;i++){
-        _h += '<i class="icon-star-empty"></i>';
+        _h += '<i class="fa fa-star-o"></i>';
   	  }
   	  $(this).html(_h);
     });