-
Notifications
You must be signed in to change notification settings - Fork 871
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds support for range query on Lucene module
refs #6534
- Loading branch information
Showing
7 changed files
with
410 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
lucene/src/main/java/com/orientechnologies/lucene/parser/OLuceneMultiFieldQueryParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package com.orientechnologies.lucene.parser; | ||
|
||
import com.orientechnologies.orient.core.metadata.schema.OType; | ||
import org.apache.lucene.analysis.Analyzer; | ||
import org.apache.lucene.document.DateTools; | ||
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser; | ||
import org.apache.lucene.queryparser.classic.ParseException; | ||
import org.apache.lucene.search.LegacyNumericRangeQuery; | ||
import org.apache.lucene.search.Query; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* Created by frank on 13/12/2016. | ||
*/ | ||
public class OLuceneMultiFieldQueryParser extends MultiFieldQueryParser { | ||
private final Map<String, OType> types; | ||
|
||
public OLuceneMultiFieldQueryParser(Map<String, OType> types, String[] fields, | ||
Analyzer analyzer, | ||
Map<String, Float> boosts) { | ||
super(fields, analyzer, boosts); | ||
this.types = types; | ||
} | ||
|
||
public OLuceneMultiFieldQueryParser(Map<String, OType> types, String[] fields, Analyzer analyzer) { | ||
super(fields, analyzer); | ||
this.types = types; | ||
} | ||
|
||
@Override | ||
protected Query getFieldQuery(String field, String queryText, int slop) throws ParseException { | ||
Query query = getQuery(field, queryText, queryText, true, true); | ||
if (query != null) | ||
return query; | ||
|
||
return super.getFieldQuery(field, queryText, slop); | ||
} | ||
|
||
@Override | ||
protected Query getFieldQuery(String field, String queryText, boolean quoted) throws ParseException { | ||
|
||
Query query = getQuery(field, queryText, queryText, true, true); | ||
if (query != null) | ||
return query; | ||
|
||
return super.getFieldQuery(field, queryText, quoted); | ||
} | ||
|
||
@Override | ||
protected Query getRangeQuery(String field, String part1, String part2, boolean startInclusive, boolean endInclusive) | ||
throws ParseException { | ||
|
||
Query query = getQuery(field, part1, part2, startInclusive, endInclusive); | ||
if (query != null) | ||
return query; | ||
|
||
return super.getRangeQuery(field, part1, part2, startInclusive, endInclusive); | ||
} | ||
|
||
private Query getQuery(String field, String part1, String part2, boolean startInclusive, boolean endInclusive) | ||
throws ParseException { | ||
|
||
if (types.containsKey(field)) { | ||
switch (types.get(field)) { | ||
case LONG: | ||
return LegacyNumericRangeQuery.newLongRange(field, Long.parseLong(part1), Long.parseLong(part2), | ||
startInclusive, endInclusive); | ||
case INTEGER: | ||
return LegacyNumericRangeQuery.newIntRange(field, Integer.parseInt(part1), Integer.parseInt(part2), | ||
startInclusive, endInclusive); | ||
case DOUBLE: | ||
return LegacyNumericRangeQuery.newDoubleRange(field, Double.parseDouble(part1), Double.parseDouble(part2), | ||
startInclusive, endInclusive); | ||
case DATE: | ||
case DATETIME: | ||
try { | ||
return LegacyNumericRangeQuery.newLongRange(field, DateTools.stringToTime(part1), DateTools.stringToTime(part2), | ||
startInclusive, endInclusive); | ||
} catch (java.text.ParseException e) { | ||
throw new ParseException(e.getMessage()); | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
} |
125 changes: 125 additions & 0 deletions
125
lucene/src/test/java/com/orientechnologies/lucene/test/LuceneRangeTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
package com.orientechnologies.lucene.test; | ||
|
||
import com.orientechnologies.orient.core.metadata.schema.OClass; | ||
import com.orientechnologies.orient.core.metadata.schema.OSchema; | ||
import com.orientechnologies.orient.core.metadata.schema.OType; | ||
import com.orientechnologies.orient.core.record.impl.ODocument; | ||
import com.orientechnologies.orient.core.sql.OCommandSQL; | ||
import org.apache.lucene.document.DateTools; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
|
||
/** | ||
* Created by frank on 13/12/2016. | ||
*/ | ||
public class LuceneRangeTest extends BaseLuceneTest { | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
OSchema schema = db.getMetadata().getSchema(); | ||
|
||
OClass cls = schema.createClass("Person"); | ||
cls.createProperty("name", OType.STRING); | ||
cls.createProperty("surname", OType.STRING); | ||
cls.createProperty("date", OType.DATETIME); | ||
cls.createProperty("age", OType.INTEGER); | ||
|
||
List<String> names = Arrays.asList("John", "Robert", "Jane", "andrew", "Scott", "luke", "Enriquez", "Luis", "Gabriel", "Sara"); | ||
for (int i = 0; i < 10; i++) { | ||
db.save(new ODocument("Person") | ||
.field("name", names.get(i)) | ||
.field("surname", "Reese") | ||
//from today back one day a time | ||
.field("date", System.currentTimeMillis() - (i * 3600 * 24 * 1000)) | ||
.field("age", i)); | ||
} | ||
|
||
} | ||
|
||
@Test | ||
public void shouldUseRangeQueryOnSingleIntegerField() throws Exception { | ||
|
||
db.command(new OCommandSQL("create index Person.age on Person(age) FULLTEXT ENGINE LUCENE")).execute(); | ||
|
||
assertThat(db.getMetadata().getIndexManager().getIndex("Person.age").getSize()).isEqualTo(10); | ||
|
||
//range | ||
Collection<ODocument> results = db.command( | ||
new OCommandSQL("SELECT FROM Person WHERE age LUCENE 'age:[5 TO 6]'")) | ||
.execute(); | ||
|
||
assertThat(results).hasSize(2); | ||
|
||
//single value | ||
results = db.command( | ||
new OCommandSQL("SELECT FROM Person WHERE age LUCENE 'age:5'")) | ||
.execute(); | ||
|
||
assertThat(results).hasSize(1); | ||
} | ||
|
||
@Test | ||
public void shouldUseRangeQueryOnSingleDateField() throws Exception { | ||
|
||
db.commit(); | ||
db.command(new OCommandSQL("create index Person.date on Person(date) FULLTEXT ENGINE LUCENE")).execute(); | ||
db.commit(); | ||
|
||
assertThat(db.getMetadata().getIndexManager().getIndex("Person.date").getSize()).isEqualTo(10); | ||
|
||
String today = DateTools.timeToString(System.currentTimeMillis(), DateTools.Resolution.MINUTE); | ||
String fiveDaysAgo = DateTools.timeToString(System.currentTimeMillis() - (5 * 3600 * 24 * 1000), DateTools.Resolution.MINUTE); | ||
|
||
//range | ||
Collection<ODocument> results = db.command( | ||
new OCommandSQL("SELECT FROM Person WHERE date LUCENE 'date:[" + fiveDaysAgo + " TO " + today + "]'")) | ||
.execute(); | ||
|
||
assertThat(results).hasSize(5); | ||
|
||
} | ||
|
||
@Test | ||
public void shouldUseRangeQueryMultipleField() throws Exception { | ||
|
||
db.command(new OCommandSQL("create index Person.composite on Person(name,surname,date,age) FULLTEXT ENGINE LUCENE")).execute(); | ||
|
||
assertThat(db.getMetadata().getIndexManager().getIndex("Person.composite").getSize()).isEqualTo(10); | ||
|
||
db.commit(); | ||
|
||
String today = DateTools.timeToString(System.currentTimeMillis(), DateTools.Resolution.MINUTE); | ||
String fiveDaysAgo = DateTools.timeToString(System.currentTimeMillis() - (5 * 3600 * 24 * 1000), DateTools.Resolution.MINUTE); | ||
|
||
//anme and age range | ||
Collection<ODocument> results = db.command( | ||
new OCommandSQL("SELECT * FROM Person WHERE [name,surname,date,age] LUCENE 'name:luke age:[5 TO 6]'")) | ||
.execute(); | ||
|
||
assertThat(results).hasSize(2); | ||
|
||
//date range | ||
results = db.command( | ||
new OCommandSQL("SELECT FROM Person WHERE [name,surname,date,age] LUCENE 'date:[" + fiveDaysAgo + " TO " + today + "]'")) | ||
.execute(); | ||
|
||
assertThat(results).hasSize(5); | ||
|
||
//age and date range with MUST | ||
results = db.command( | ||
new OCommandSQL( | ||
"SELECT FROM Person WHERE [name,surname,date,age] LUCENE '+age:[4 TO 7] +date:[" + fiveDaysAgo + " TO " + today | ||
+ "]'")) | ||
.execute(); | ||
|
||
assertThat(results).hasSize(2); | ||
|
||
} | ||
|
||
} |
Oops, something went wrong.