Solr's Function Query has a lot of useful things,
https://wiki.apache.org/solr/FunctionQuery#Available_Functions
I think that the above functions alone may not meet the requirements.
This time, I will create a FunctionQuery by assuming that the JSON format character string registered in a certain field is parsed, some processing is performed, and then the result is returned.
This article http://www.lifull.blog/entry/2014/02/25/145220 I created it with reference to. The above article is enough to be helpful, so I think some people can make their own. In this article, we will take a closer look at the Solr source code and create it, including explanations of what kind of class structure it has.
First, refer to the implementation of the function provided by default.
https://github.com/apache/lucene-solr/blob/master/solr/core/src/java/org/apache/solr/search/ValueSourceParser.java The provided FunctionQuery is implemented as an object of ValueSourceParser class in the above source.
The ValueSourceParser class has the following signatures:
public abstract class ValueSourceParser implements NamedListInitializedPlugin {
/**
* Initialize the plugin.
*/
@Override
public void init(NamedList args) {}
/**
* Parse the user input into a ValueSource.
*/
public abstract ValueSource parse(FunctionQParser fp) throws SyntaxError;
...
Also, in the initialization block </ span> of the ValueSourceParser class
addParser("abs", new ValueSourceParser() {
@Override
public ValueSource parse(FunctionQParser fp) throws SyntaxError {
ValueSource source = fp.parseValueSource();
return new SimpleFloatFunction(source) {
@Override
protected String name() {
return "abs";
}
@Override
protected float func(int doc, FunctionValues vals) {
return Math.abs(vals.floatVal(doc));
}
};
}
});
The default function is created like this.
Please note
of ʻabs (a_value)
can be obtained as ValueSource
type withfp.parseValueSource ()
.is.
The definition of SimpleFloatFunction is
https://github.com/apache/lucene-solr/blob/master/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleFloatFunction.java
It is defined in.
...
/** A simple float function with a single argument
*/
public abstract class SimpleFloatFunction extends SingleFunction {
public SimpleFloatFunction(ValueSource source) {
super(source);
}
protected abstract float func(int doc, FunctionValues vals) throws IOException;
@Override
public FunctionValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
final FunctionValues vals = source.getValues(context, readerContext);
return new FloatDocValues(this) {
@Override
public float floatVal(int doc) throws IOException {
return func(doc, vals);
}
@Override
public String toString(int doc) throws IOException {
return name() + '(' + vals.toString(doc) + ')';
}
};
}
...
It reads the abs () argument in a method called getValues and returns an instance of the FloatDocValues class (which inherits from the FunctionValues class). The floatVal method of the FloatDocValues class calls the Overridden func method (#initialize) to call the Math.abs function, which ultimately returns the absolute value.
https://github.com/apache/lucene-solr/blob/master/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/
If you look at some of the classes defined in the above directory, you can see the same.
It is implemented as.
Also, https://wiki.apache.org/solr/SolrPlugins#ValueSourceParser
If you look at the above documentation, you can create your own class and give it a function name by setting it in solrconfig.xml
.
From the above, the necessary work is
This time I want to create a FunctionQuery that takes a string as an argument and returns a Bool type
https://github.com/apache/lucene-solr/blob/master/lucene/queries/src/java/org/apache/lucene/queries/function/valuesource/SimpleBoolFunction.java
It seems that this Simple Bool Function can be used.
/**
* {@link BoolFunction} implementation which applies an extendible boolean
* function to the values of a single wrapped {@link ValueSource}.
*
* Functions this can be used for include whether a field has a value or not,
* or inverting the boolean value of the wrapped ValueSource.
*/
public abstract class SimpleBoolFunction extends BoolFunction {
protected final ValueSource source;
public SimpleBoolFunction(ValueSource source) {
this.source = source;
}
protected abstract String name();
protected abstract boolean func(int doc, FunctionValues vals) throws IOException;
@Override
public BoolDocValues getValues(Map context, LeafReaderContext readerContext) throws IOException {
final FunctionValues vals = source.getValues(context, readerContext);
return new BoolDocValues(this) {
@Override
public boolean boolVal(int doc) throws IOException {
return func(doc, vals);
}
@Override
public String toString(int doc) throws IOException {
return name() + '(' + vals.toString(doc) + ')';
}
};
}
If you rewrite the necessary work
Will be. Perform the above work to create your own Function Query.
package com.overseas_lifull.solr.functionquery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.search.SyntaxError;
import org.apache.solr.search.FunctionQParser;
import org.apache.solr.search.ValueSourceParser;
public class PremiumParser extends ValueSourceParser {
@Override
public void init(NamedList namedList) {
}
@Override
public ValueSource parse(FunctionQParser fp) throws SyntaxError {
ValueSource premiumInfo = fp.parseValueSource();
return new PremiumFunction(premiumInfo);
}
}
The value of premiumInfo received as an argument is passed to the function called PremiumFunction that will be defined later. This PremiumFunction is a class that inherits SimpleBoolFunction.
package com.overseas_lifull.solr.functionquery;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.valuesource.SimpleBoolFunction;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Date;
public class PremiumFunction extends SimpleBoolFunction {
public PremiumFunction(ValueSource source) {
super(source);
}
protected String name() {
return "isPremium";
}
protected boolean func(int doc, FunctionValues vals) {
boolean result = false;
String jsonStr = vals.strVal(doc); //Get the argument of the isPremium function as a string
/*Process string and true,Returns false
* ...Various processing*/
if (/*Judgment condition*/) {
return true;
} else {
return false;
}
}
}
Compile and place it in the directory that Solr expects, and edit solrconfig.xml.
$ javac -classpath "./lib/*:/opt/solr-5.5.3/server/solr-webapp/webapp/WEB-INF/lib/lucene-core-5.5.3.jar:/opt/solr-5.5.3/server/solr-webapp/webapp/WEB-INF/lib/lucene-queries-5.5.3.jar:/opt/solr-5.5.3/server/solr-webapp/webapp/WEB-INF/lib/lucene-queryparser-5.5.3.jar:/opt/solr-5.5.3/server/solr-webapp/webapp/WEB-INF/lib/solr-core-5.5.3.jar:/opt/solr-5.5.3/server/solr-webapp/webapp/WEB-INF/lib/solr-solrj-5.5.3.jar" com/overseas_lifull/solr/functionquery/PremiumFunction.java com/overseas_lifull/solr/functionquery/PremiumParser.java com/overseas_lifull/solr/functionquery/PremiumData.java
The classpath you specify depends on the class you use and the location of the source.
$ jar cvf premiumQueryFunction.jar ./com/overseas_lifull/solr/functionquery/PremiumData.class ./com/overseas_lifull/solr/functionquery/PremiumData.java ./com/overseas_lifull/solr/functionquery/PremiumFunction.class ./com/overseas_lifull/solr/functionquery/PremiumFunction.java ./com/overseas_lifull/solr/functionquery/PremiumParser.class ./com/overseas_lifull/solr/functionquery/PremiumParser.java
Create a lib
directory in the Solr core directory and place it there.
The directory structure should look like the one below.
conf/
admin-extra.html
admin-extra.menu-bottom.html
admin-extra.menu-top.html
data-config.xml
dataimport.properties
elevate.xml
schema.xml
solrconfig.xml
lib/
premiumQueryFunction.jar
core.properties
<valueSourceParser name="isPremium" class="com.overseas_lifull.solr.functionquery.PremiumParser" />
Restart Solr to load the edited solrconfig.xml and the placed jar file.
http://localhost:8983/solr/my_core/select?q=*:*&fl=*,isPremium(flat_premium_data)&wt=json&indent=true
In the document returned as a response ʻIsPremium (flat_premium_data): Success if there is a field and value (true or false) like true`.
Recommended Posts