[Groonga-commit] groonga/gcs [master] Support facets of simple case for literal fields

Back to archive index

null+****@clear***** null+****@clear*****
2012年 8月 2日 (木) 14:37:12 JST


Yoji SHIDARA	2012-08-02 14:37:12 +0900 (Thu, 02 Aug 2012)

  New Revision: 7496a8cc016bedee423f95d7069ad52ffee86f7c
  https://github.com/groonga/gcs/commit/7496a8cc016bedee423f95d7069ad52ffee86f7c

  Log:
    Support facets of simple case for literal fields
    
    Sorts and limits for the facets are not supported.

  Modified files:
    lib/api/2011-02-01/search.js
    test/api-search.test.js

  Modified: lib/api/2011-02-01/search.js (+76 -27)
===================================================================
--- lib/api/2011-02-01/search.js    2012-08-02 10:51:53 +0900 (2f81e53)
+++ lib/api/2011-02-01/search.js    2012-08-02 14:37:12 +0900 (683bc33)
@@ -4,6 +4,32 @@ var Domain = require('../../database').Domain;
 var nroonga = require('../../wrapped-nroonga');
 var BooleanQueryTranslator = require('../../bq-translator').BooleanQueryTranslator;
 
+function formatFacets(data) {
+  var drilldownRecords = data.slice(1);
+
+  return drilldownRecords.map(function(drilldownRecord, index) {
+    return formatFacet(drilldownRecord);
+  });
+}
+
+function formatFacet(drilldownRecord) {
+  var columnList = drilldownRecord[1];
+  var columnNames = columnList.map(function(column) {
+    return column[0];
+  });
+
+  var constraintEntries = drilldownRecord.slice(2);
+  var constraints = constraintEntries.map(function(record) {
+    var object = {};
+    columnNames.forEach(function(columnName, index) {
+      object[columnName] = record[index];
+    });
+    return {value: object._key, count: object._nsubrecs};
+  });
+
+  return {constraints: constraints};
+}
+
 function formatSelectResults(data) {
   var columnList = data[0][1];
   var columnNames = columnList.map(function(column) {
@@ -30,7 +56,12 @@ function select(context, options, callback) {
       callback(error);
     } else {
       var numFoundRecords = data[0][0][0];
-      callback(null, formatSelectResults(data), numFoundRecords);
+      callback(
+        null,
+        formatSelectResults(data),
+        numFoundRecords,
+        formatFacets(data)
+      );
     }
   });
 }
@@ -59,6 +90,7 @@ exports.createHandler = function(context) {
     var query = request.query.q || '';
     var booleanQuery = request.query.bq || '';
     var filter = null;
+    var facet = request.query.facet;
 
     if (booleanQuery) {
       var translator = new BooleanQueryTranslator();
@@ -100,33 +132,50 @@ exports.createHandler = function(context) {
       options.filter = filter;
     }
 
-    select(context, options, function(error, data, numFoundRecords) {
-      var finishedAt = new Date();
-      var elapsedTime = finishedAt - startedAt;
-      var info = {
-        rid: dummyRid,
-        'time-ms': elapsedTime,
-        'cpu-time-ms': 0 // TODO
-      };
-      if (error) {
-        var body = createErrorBody({
+    if (facet) {
+      options.drilldown = facet;
+      // TODO support sorting
+      // TODO support facet-FIELD-top-n parameter
+    }
+
+    select(context, options,
+      function(error, data, numFoundRecords, facets) {
+        var finishedAt = new Date();
+        var elapsedTime = finishedAt - startedAt;
+        var info = {
           rid: dummyRid,
-          message: error.message,
-          elapsedTime: elapsedTime
-        });
-        return response.send(body, 400); // TODO
+          'time-ms': elapsedTime,
+          'cpu-time-ms': 0 // TODO
+        };
+        if (error) {
+          var body = createErrorBody({
+            rid: dummyRid,
+            message: error.message,
+            elapsedTime: elapsedTime
+          });
+          return response.send(body, 400); // TODO
+        }
+        var result = {
+          rank: '-text_relevance', // FIXME
+          'match-expr': '', // FIXME
+          hits: {
+            found: numFoundRecords,
+            start: start,
+            hit: data
+          },
+          info: info
+        };
+        if (facets) {
+          var facetNames = facet.split(',');
+          var facetsObject = {};
+          facets.map(function(facet, index) {
+            var facetName = facetNames[index];
+            facetsObject[facetName] = facet;
+          });
+          result.facets = facetsObject;
+        }
+        response.json(result);
       }
-      var result = {
-        rank: '-text_relevance', // FIXME
-        'match-expr': '', // FIXME
-        hits: {
-          found: numFoundRecords,
-          start: start,
-          hit: data
-        },
-        info: info
-      };
-      response.json(result);
-    });
+    );
   };
 };

  Modified: test/api-search.test.js (+72 -0)
===================================================================
--- test/api-search.test.js    2012-08-02 10:51:53 +0900 (7e1e874)
+++ test/api-search.test.js    2012-08-02 14:37:12 +0900 (5204111)
@@ -151,6 +151,78 @@ suite('Search API', function() {
         done();
       }
     );
+    testSearch('/2011-02-01/search?q=Tokyo&facet=product',
+               'with facet "domain"',
+               'search-companies-00000000000000000000000000.localhost',
+      function(response, body, done) {
+        var normalizedBody = normalizeSearchResult(body);
+        var actual = JSON.parse(normalizedBody);
+        var expected = {
+          rank: '-text_relevance',
+          'match-expr': '',
+          hits: {
+            found: 3,
+            start: 0,
+            hit: [
+              {
+                id: 'id1',
+                data: {
+                  _id: [1],
+                  _key: ['id1'],
+                  address: ['Shibuya, Tokyo, Japan'],
+                  description: [''],
+                  email_address: ['info****@razil*****'],
+                  name: ['Brazil'],
+                  age: [1],
+                  product: ['groonga']
+                }
+              },
+              {
+                id: 'id3',
+                data: {
+                  _id: [3],
+                  _key: ['id3'],
+                  address: ['Hongo, Tokyo, Japan'],
+                  description: [''],
+                  email_address: ['info****@clear*****'],
+                  name: ['ClearCode Inc.'],
+                  age: [3],
+                  product: ['groonga']
+                }
+              },
+              {
+                id: 'id9',
+                data: {
+                  _id: [9],
+                  _key: ['id9'],
+                  address: ['Tokyo, Japan'],
+                  description: [''],
+                  email_address: [''],
+                  name: ['Umbrella Corporation'],
+                  age: [9],
+                  product: ['tyrant']
+                }
+              }
+            ]
+          },
+          facets: {
+            product: {
+              constraints: [
+                {value: 'groonga', count: 2},
+                {value: 'tyrant', count: 1}
+              ]
+            }
+          },
+          info: {
+            rid: '000000000000000000000000000000000000000000000000000000000000000',
+            'time-ms': 0, // always 0
+            'cpu-time-ms': 0
+          }
+        };
+        assert.deepEqual(actual, expected);
+        done();
+      }
+    );
 
     testSearch('/2011-02-01/search?q=Tokyo&size=2',
                'should return two hit entries',
-------------- next part --------------
HTML$B$NE:IU%U%!%$%k$rJ]4I$7$^$7$?(B...
Download 



Groonga-commit メーリングリストの案内
Back to archive index