Navigation Menu

Skip to content

Commit

Permalink
bq: support query expansion in keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
kou committed Aug 14, 2012
1 parent 805c7da commit 1b79691
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 26 deletions.
2 changes: 2 additions & 0 deletions lib/api/2011-02-01/search.js
Expand Up @@ -106,6 +106,7 @@ exports.createHandler = function(context) {
if (query) {
var queryAsBooleanQuery = translateQueryToBooleanQuery(query);
var translator = new BooleanQueryTranslator(queryAsBooleanQuery);
translator.domain = domain;
translator.defaultFieldNames = defaultFieldNames;
try {
filters.push(translator.translate());
Expand All @@ -121,6 +122,7 @@ exports.createHandler = function(context) {

if (booleanQuery) {
var translator = new BooleanQueryTranslator(booleanQuery);
translator.domain = domain;
translator.defaultFieldNames = defaultFieldNames;
try {
filters.push(translator.translate());
Expand Down
38 changes: 27 additions & 11 deletions lib/bq-translator.js
Expand Up @@ -17,6 +17,7 @@
function BooleanQueryTranslator(query) {
this.query = query;
this.offset = 0;
this.domain = null;
this.defaultFieldNames = null;
}

Expand Down Expand Up @@ -217,27 +218,35 @@ BooleanQueryTranslator.prototype = {

var tokens = [];
var value = "";
var self = this;
var addKeywordToken = function() {
if (value.length == 0) {
return;
}
var expandedKeywords = self.expandWord(value);
var keywordTokens = expandedKeywords.map(function(keyword) {
return this.translateExpressionValueStringKeyword(field, keyword);
}, self);
if (keywordTokens.length >= 2) {
tokens.push("(" + keywordTokens.join(" || ") + ")");
} else {
tokens.push(keywordTokens[0]);
}
value = "";
};
for (; this.offset < this.query.length; this.offset++) {
var character = this.query[this.offset];
if (character == "'") {
this.offset++;
if (value.length > 0) {
tokens.push(this.translateExpressionValueStringKeyword(field, value));
}
addKeywordToken();
return tokens.join(" ");
}

if (character == " " || character == "+") {
if (value.length > 0) {
tokens.push(this.translateExpressionValueStringKeyword(field, value));
value = "";
}
addKeywordToken();
tokens.push("&&");
} else if (character == "|") {
if (value.length > 0) {
tokens.push(this.translateExpressionValueStringKeyword(field, value));
value = "";
}
addKeywordToken();
tokens.push("||");
} else if (character == "\\") {
this.offset++;
Expand Down Expand Up @@ -338,6 +347,13 @@ BooleanQueryTranslator.prototype = {
return this.constructBinaryOperation(field, "==", min);
}
},
expandWord: function(word) {
var synonym = this.domain.getSynonymSync(word);
if (!synonym) {
return [word];
}
return synonym;
},
constructBinaryOperation: function(field, operator, value) {
if (field) {
return field + " " + operator + " " + value;
Expand Down
1 change: 0 additions & 1 deletion test/api-search.test.js
Expand Up @@ -356,7 +356,6 @@ suite('Search API', function() {
});

suite('with fixture and synonyms loaded', function() {
return; // TODO: Re-enable me. Disabled temporary
setup(function() {
utils.loadDumpFile(context, __dirname + '/fixture/companies/ddl.grn');
utils.loadDumpFile(context, __dirname + '/fixture/companies/data.grn');
Expand Down
63 changes: 49 additions & 14 deletions test/bq-translator.test.js
Expand Up @@ -5,20 +5,29 @@ var assert = require('chai').assert;

var BooleanQueryTranslator = require('../lib/bq-translator').BooleanQueryTranslator;

function createTranslator(query) {
var translator = new BooleanQueryTranslator(query);
translator.domain = {
getSynonymSync: function(key) {
return null;
}
};
translator.defaultFieldNames = ["field"];
return translator;
}

function testQuery(label, query, expected) {
test('query: ' + label + ': ' +
'<' + query + '> -> <' + expected + '>', function() {
var translator = new BooleanQueryTranslator(query);
translator.defaultFieldNames = ["field"];
var translator = createTranslator(query);
assert.equal(translator.translate(),
expected);
});
}

function testQueryError(label, query, context, detail) {
test('error: query: ' + label + ': ' + '<' + query + '>', function() {
var translator = new BooleanQueryTranslator(query);
translator.defaultFieldNames = ["field"];
var translator = createTranslator(query);
var actualError;
assert.throw(function() {
try {
Expand All @@ -35,8 +44,7 @@ function testQueryError(label, query, context, detail) {
function testGroup(label, group, expectedOffset, expectedScriptGrnExpr) {
test('gorup: ' + label + ': ' +
'<' + group + '> -> <' + expectedScriptGrnExpr + '>', function() {
var translator = new BooleanQueryTranslator(group);
translator.defaultFieldNames = ["field"];
var translator = createTranslator(group);
var actualScriptGrnExpr = translator.translateGroup();
assert.deepEqual({
scriptGrnExpr: actualScriptGrnExpr,
Expand All @@ -51,8 +59,7 @@ function testGroup(label, group, expectedOffset, expectedScriptGrnExpr) {

function testGroupError(label, group, context, detail) {
test('error: group: ' + label + ': ' + '<' + group + '>', function() {
var translator = new BooleanQueryTranslator(group);
translator.defaultFieldNames = ["field"];
var translator = createTranslator(group);
var actualError;
assert.throw(function() {
try {
Expand All @@ -70,8 +77,7 @@ function testExpression(label, expression,
expectedOffset, expectedScriptGrnExpr) {
test('expression: ' + label + ': ' +
'<' + expression + '> -> <' + expectedScriptGrnExpr + '>', function() {
var translator = new BooleanQueryTranslator(expression);
translator.defaultFieldNames = ["field"];
var translator = createTranslator(expression);
var actualScriptGrnExpr =
translator.translateExpression();
assert.deepEqual({
Expand All @@ -88,8 +94,7 @@ function testExpression(label, expression,
function testExpressionError(label, expression, context, detail) {
test('error: expression: ' + label + ': ' + '<' + expression + '>',
function() {
var translator = new BooleanQueryTranslator(expression);
translator.defaultFieldNames = ["field"];
var translator = createTranslator(expression);
var actualError;
assert.throw(function() {
try {
Expand All @@ -106,7 +111,7 @@ function testExpressionError(label, expression, context, detail) {
function testDefaultFieldNames(label, query, defaultFieldNames, expected) {
test('default field names: ' + label + ': ' +
'<' + query + '> -> <' + expected + '>', function() {
var translator = new BooleanQueryTranslator(query);
var translator = createTranslator(query);
translator.defaultFieldNames = defaultFieldNames;
assert.equal(translator.translate(),
expected);
Expand All @@ -117,7 +122,7 @@ function testDefaultFieldNamesError(label, query, defaultFieldNames,
context, detail) {
test('error: default field names: ' + label + ': ' + '<' + query + '>',
function() {
var translator = new BooleanQueryTranslator(query);
var translator = createTranslator(query);
translator.defaultFieldNames = defaultFieldNames;
var actualError;
assert.throw(function() {
Expand All @@ -132,6 +137,19 @@ function testDefaultFieldNamesError(label, query, defaultFieldNames,
});
}

function testSynonym(label, query, synonyms, expected) {
test('default synonym: ' + label + ': ' +
'<' + query + '> -> <' + expected + '>', function() {
var translator = createTranslator(query);
translator.domain = {
getSynonymSync: function(key) {
return synonyms[key];
}
};
assert.equal(translator.translate(), expected);
});
}

suite('BoolanQueryTranslator', function() {
testQuery("expression",
"type:'ModelName'",
Expand Down Expand Up @@ -331,4 +349,21 @@ suite('BoolanQueryTranslator', function() {
[],
"'ModelName'||",
"no default field");

testSynonym("existent: 0 synonym",
"'tokio'",
{ tokio: [] },
'');
testSynonym("existent: 1 synonym",
"'tokio'",
{ tokio: ["tokyo"] },
'field @ "tokyo"');
testSynonym("existent: N synonyms",
"'tokio'",
{ tokio: ["tokio", "tokyo"] },
'(field @ "tokio" || field @ "tokyo")');
testSynonym("nonexistent",
"'hokkaido'",
{ tokio: ["tokio", "tokyo"] },
'field @ "hokkaido"');
});

0 comments on commit 1b79691

Please sign in to comment.