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