Browse Source

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 năm trước cách đây
mục cha
commit
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);
     });