com.jaeksoft.searchlib.request.SearchField Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opensearchserver Show documentation
Show all versions of opensearchserver Show documentation
OpenSearchServer is a powerful, enterprise-class, search engine program. Using the web user interface, the crawlers (web, file, database, ...) and the REST/RESTFul API you will be able to integrate quickly and easily advanced full-text search capabilities in your application. OpenSearchServer runs on Windows and Linux/Unix/BSD.
The newest version!
/**
* License Agreement for OpenSearchServer
*
* Copyright (C) 2013-2015 Emmanuel Keller / Jaeksoft
*
* http://www.open-search-server.com
*
* This file is part of OpenSearchServer.
*
* OpenSearchServer is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenSearchServer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenSearchServer.
* If not, see .
**/
package com.jaeksoft.searchlib.request;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.Query;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import com.jaeksoft.searchlib.analysis.CompiledAnalyzer;
import com.jaeksoft.searchlib.analysis.PerFieldAnalyzer;
import com.jaeksoft.searchlib.analysis.TokenQueryFilter;
import com.jaeksoft.searchlib.analysis.TokenQueryFilter.TermQueryFilter;
import com.jaeksoft.searchlib.analysis.TokenQueryFilter.TermQueryItem;
import com.jaeksoft.searchlib.query.QueryParser;
import com.jaeksoft.searchlib.util.DomUtils;
import com.jaeksoft.searchlib.util.IOUtils;
import com.jaeksoft.searchlib.util.XmlWriter;
import com.jaeksoft.searchlib.webservice.query.search.SearchFieldQuery.SearchField.Mode;
public class SearchField implements Cloneable {
public final static String SEARCHFIELD_NODE_NAME = "searchField";
public final static String SEARCHFIELD_ATTRIBUTE_FIELD_NAME = "field";
public final static String SEARCHFIELD_ATTRIBUTE_MODE = "mode";
public final static String SEARCHFIELD_ATTRIBUTE_PHRASE = "phrase";
public final static String SEARCHFIELD_ATTRIBUTE_TERM_BOOST = "boost";
public final static String SEARCHFIELD_ATTRIBUTE_PHRASE_BOOST = "phraseBoost";
public final static String SEARCHFIELD_ATTRIBUTE_PHRASE_SLOP = "phraseSlop";
public final static String SEARCHFIELD_ATTRIBUTE_BOOLEAN_GROUP = "booleanGroup";
private String field;
private Mode mode;
private double termBoost;
private double phraseBoost;
private Integer phraseSlop;
private Integer booleanGroup;
private SearchField(SearchField searchField) {
this.field = searchField.field;
this.mode = searchField.mode;
this.termBoost = searchField.termBoost;
this.phraseBoost = searchField.phraseBoost;
this.phraseSlop = searchField.phraseSlop;
this.booleanGroup = searchField.booleanGroup;
}
public SearchField(String field, Mode mode, Double termBoost, Double phraseBoost, Integer phraseSlop,
Integer booleanGroup) {
this.field = field;
this.mode = mode == null ? Mode.TERM : mode;
this.termBoost = termBoost == null ? 1.0F : termBoost;
this.phraseBoost = phraseBoost == null ? this.termBoost : phraseBoost;
this.phraseSlop = phraseSlop;
this.booleanGroup = booleanGroup;
}
public SearchField(Node fieldNode) {
this.field = DomUtils.getAttributeText(fieldNode, SEARCHFIELD_ATTRIBUTE_FIELD_NAME);
String modeAttr = DomUtils.getAttributeText(fieldNode, SEARCHFIELD_ATTRIBUTE_MODE);
if (modeAttr == null) {
boolean phrase = Boolean.parseBoolean(DomUtils.getAttributeText(fieldNode, SEARCHFIELD_ATTRIBUTE_PHRASE));
mode = phrase ? Mode.TERM_AND_PHRASE : Mode.TERM;
} else
mode = Mode.find(modeAttr);
this.termBoost = DomUtils.getAttributeDouble(fieldNode, SEARCHFIELD_ATTRIBUTE_TERM_BOOST, 1.0);
this.phraseBoost = DomUtils.getAttributeDouble(fieldNode, SEARCHFIELD_ATTRIBUTE_PHRASE_BOOST, this.termBoost);
this.phraseSlop = DomUtils.getAttributeInteger(fieldNode, SEARCHFIELD_ATTRIBUTE_PHRASE_SLOP, null);
this.booleanGroup = DomUtils.getAttributeInteger(fieldNode, SEARCHFIELD_ATTRIBUTE_BOOLEAN_GROUP, null);
}
@Override
public SearchField clone() {
return new SearchField(this);
}
/**
* @return the field
*/
public String getField() {
return field;
}
/**
* @param field
* the field to set
*/
public void setField(String field) {
this.field = field;
}
/**
* @return the mode
*/
public Mode getMode() {
return mode;
}
/**
* @param mode
* the mode to set
*/
public void setMode(Mode mode) {
this.mode = mode;
}
/**
* @return the termBoost
*/
public double getTermBoost() {
return termBoost;
}
/**
* @param termBoost
* the termBoost to set
*/
public void setTermBoost(double termBoost) {
this.termBoost = termBoost;
}
/**
* @return the phrase boost
*/
public double getPhraseBoost() {
return phraseBoost;
}
/**
* @param phrase
* boost the phrase boost to set
*/
public void setPhraseBoost(double phraseBoost) {
this.phraseBoost = phraseBoost;
}
/**
* @return the phrase slop
*/
public Integer getPhraseSlop() {
return phraseSlop;
}
/**
* @param phrase
* slop the phrase slop to set
*/
public void setPhraseSlop(Integer phraseSlop) {
this.phraseSlop = phraseSlop;
}
/**
* @return the booleanGroup
*/
public Integer getBooleanGroup() {
return booleanGroup;
}
/**
* @param booleanGroup
* the booleanGroup to set
*/
public void setBooleanGroup(Integer booleanGroup) {
this.booleanGroup = booleanGroup;
}
public void writeXmlConfig(XmlWriter xmlWriter) throws SAXException {
xmlWriter.startElement(SEARCHFIELD_NODE_NAME, SEARCHFIELD_ATTRIBUTE_FIELD_NAME, field,
SEARCHFIELD_ATTRIBUTE_MODE, mode == null ? null : mode.name(), SEARCHFIELD_ATTRIBUTE_TERM_BOOST,
Double.toString(termBoost), SEARCHFIELD_ATTRIBUTE_PHRASE_BOOST, Double.toString(phraseBoost),
SEARCHFIELD_ATTRIBUTE_PHRASE_SLOP, phraseSlop == null ? null : Integer.toString(phraseSlop),
SEARCHFIELD_ATTRIBUTE_BOOLEAN_GROUP, booleanGroup == null ? null : Integer.toString(booleanGroup));
xmlWriter.endElement();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(field);
sb.append(" - ");
sb.append(mode.getLabel());
sb.append(" - ");
sb.append(termBoost);
sb.append("/");
sb.append(phraseBoost);
if (phraseSlop != null) {
sb.append("/");
sb.append(phraseSlop);
}
if (booleanGroup != null) {
sb.append("/");
sb.append(booleanGroup);
}
return sb.toString();
}
final private Query getPatternQuery(final Set fields, final CompiledAnalyzer analyzer, final Occur occur,
final int phraseSlop, final String queryString) throws IOException {
QueryParser queryParser = new QueryParser(field, fields, occur, analyzer,
this.phraseSlop != null ? this.phraseSlop : phraseSlop, termBoost, phraseBoost);
return queryParser.parse(queryString);
}
final private List getTermQueryFilter(final PerFieldAnalyzer perFieldAnalyzer,
CompiledAnalyzer compiledAnalyzer, final String queryString) throws IOException {
TokenStream ts = null;
TokenQueryFilter.TermQueryFilter tqf = null;
Analyzer analyzer = compiledAnalyzer != null ? compiledAnalyzer : perFieldAnalyzer.getKeywordAnalyzer();
try {
ts = analyzer.tokenStream(field, new StringReader(queryString));
tqf = new TermQueryFilter(compiledAnalyzer, field, (float) termBoost, ts);
while (tqf.incrementToken())
;
ts.end();
ts.close();
tqf.sortByOffset();
TermQueryFilter.includeChildrenBrothers(tqf.termQueryItems);
for (TermQueryItem termQueryItem : tqf.termQueryItems)
termQueryItem.includeChildrenBrothers();
return tqf.termQueryItems;
} finally {
IOUtils.close(tqf, ts, analyzer);
}
}
final private Query getTermQuery(final List termQueryItems, final Occur occur) throws IOException {
BooleanQuery booleanQuery = new BooleanQuery();
for (TermQueryItem termQueryItem : termQueryItems)
if (termQueryItem.parent == null)
booleanQuery.add(termQueryItem.getQuery(null, occur), occur);
return booleanQuery;
}
final private void phraseAddLeaf(TermQueryItem termQueryItem, PhraseQuery phraseQuery) {
if (termQueryItem.children != null) {
for (TermQueryItem child : termQueryItem.children)
phraseAddLeaf(child, phraseQuery);
} else
phraseQuery.add(new Term(field, termQueryItem.term));
}
final private Query getPhraseQuery(final List termQueryItems, final int phraseSlop,
final Occur occur) throws IOException {
PhraseQuery phraseQuery = new PhraseQuery();
for (TermQueryItem termQueryItem : termQueryItems)
phraseAddLeaf(termQueryItem, phraseQuery);
phraseQuery.setBoost((float) phraseBoost);
phraseQuery.setSlop(this.phraseSlop != null ? this.phraseSlop : phraseSlop);
return phraseQuery;
}
final public void addQuery(Set fields, PerFieldAnalyzer perFieldAnalyzer, String queryString,
Collection queries, int phraseSlop, Occur occur) throws IOException {
CompiledAnalyzer compiledAnalyzer = null;
try {
if (StringUtils.isEmpty(queryString))
return;
compiledAnalyzer = perFieldAnalyzer.getCompiledAnalyzer(field);
if (mode == Mode.PATTERN) {
queries.add(getPatternQuery(fields, compiledAnalyzer, occur, phraseSlop, queryString));
return;
}
List termQueryItems = getTermQueryFilter(perFieldAnalyzer, compiledAnalyzer, queryString);
switch (mode) {
case TERM:
queries.add(getTermQuery(termQueryItems, occur));
break;
case PHRASE:
queries.add(getPhraseQuery(termQueryItems, phraseSlop, occur));
break;
case TERM_AND_PHRASE:
queries.add(getTermQuery(termQueryItems, occur));
queries.add(getPhraseQuery(termQueryItems, phraseSlop, occur));
break;
default:
break;
}
} finally {
IOUtils.close(compiledAnalyzer);
}
}
}