How to Boost Documents from within Solar using MongoDB
Previously, I blogged about connecting Redis to Solr for relevance boosting via a custom FunctionQuery. Now, I'll talk about doing the same with MongoDB.
In solrconfig.xml, declare your ValueSourceParser.
<valueSourceParser name="mongo" class="org.supermind.solr.mongodb.MongoDBValueSourceParser"> <str name="host">localhost</str> <str name="dbName">solr</str> <str name="collectionName">electronics</str> <str name="key">userId</str> <str name="idField">id</str> </valueSourceParser>
The host, dbName and collectionName parameters are self-explanatory.
The key parameter is used to specify how to match for a MongoDB doc. The idField parameter declares the Solr field used for matching.
Here's the ValueSourceParser.
public class MongoDBValueSourceParser extends ValueSourceParser {
private String idField;
private String dbName;
private String collectionName;
private String key;
private String host;
private DBCollection collection;
@Override public void init(NamedList args) {
host = (String) args.get("host");
idField = (String) args.get("idField");
dbName = (String) args.get("dbName");
collectionName = (String) args.get("collectionName");
key = (String) args.get("key");
try {
Mongo mongo = new Mongo(host);
collection = mongo.getDB(dbName).getCollection(collectionName);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e);
}
}
@Override public ValueSource parse(FunctionQParser fp) throws ParseException {
String value = fp.parseArg();
final DBObject obj = collection.findOne(new BasicDBObject(key, value));
return new MongoDBValueSource(idField, obj, value);
}
}Here's the interesting method in MongoDBValueSource.
@Override public DocValues getValues(Map context, IndexReader reader) throws IOException {
final String[] lookup = FieldCache.DEFAULT.getStrings(reader, idField);
return new DocValues() {
@Override public byte byteVal(int doc) {
return (byte) intVal(doc);
}
@Override public short shortVal(int doc) {
return (short) intVal(doc);
}
@Override public float floatVal(int doc) {
final String id = lookup[doc];
if (obj == null) return 0;
Object v = obj.get(id);
if (v == null) return 0;
if (v instanceof Float) {
return ((Float) v);
} else if (v instanceof Integer) {
return ((Integer) v);
} else if (v instanceof String) {
try {
return Float.parseFloat((String) v);
} catch (NumberFormatException e) {
return 0;
}
}
return 0;
}
@Override public int intVal(int doc) {
final String id = lookup[doc];
if (obj == null) return 0;
Object v = obj.get(id);
if (v == null) return 0;
if (v instanceof Integer) {
return (Integer) v;
} else if (v instanceof String) {
try {
return Integer.parseInt((String) v);
} catch (NumberFormatException e) {
return 0;
}
}
return 0;
}
@Override public long longVal(int doc) {
return intVal(doc);
}
@Override public double doubleVal(int doc) {
return floatVal(doc);
}
@Override public String strVal(int doc) {
final String id = lookup[doc];
if (obj == null) return null;
Object v = obj.get(id);
return v != null ? v.toString() : null;
}
@Override public String toString(int doc) {
return strVal(doc);
}
};
}You can now use the FunctionQuery mongo in your search requests. For example:
http://localhost:8983/solr/select?defType=edismax&q=cat:electronics&bf=mongo(1377)
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)



