SEARCH-251: Search by FINGERPRINT DBID and noderef

This commit is contained in:
Joel
2016-12-05 22:12:08 -05:00
parent a6511305a5
commit 09b0c94e1b
4 changed files with 228 additions and 31 deletions
@@ -20,17 +20,20 @@
package org.alfresco.solr.component;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Collection;
import java.util.List;
import java.util.ArrayList;
import java.util.*;
import org.alfresco.repo.search.adaptor.lucene.QueryConstants;
import org.alfresco.repo.tenant.TenantService;
import org.alfresco.solr.AlfrescoCoreAdminHandler;
import org.alfresco.solr.AlfrescoSolrDataModel;
import org.alfresco.solr.SolrInformationServer;
import org.alfresco.solr.content.SolrContentStore;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.common.util.NamedList;
@@ -38,6 +41,7 @@ import org.apache.solr.core.CoreContainer;
import org.apache.solr.core.SolrCore;
import org.apache.solr.handler.component.*;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.util.plugin.SolrCoreAware;
/**
@@ -67,22 +71,50 @@ public class FingerPrintComponent extends SearchComponent implements SolrCoreAwa
NamedList response = responseBuilder.rsp.getValues();
String id = responseBuilder.req.getParams().get("id");
NamedList fingerPrint = new NamedList();
SolrInputDocument solrDoc = solrContentStore.retrieveDocFromSolrContentStore(AlfrescoSolrDataModel.getTenantId(TenantService.DEFAULT_DOMAIN), Long.parseLong(id));
if(solrDoc != null) {
SolrInputField mh = solrDoc.getField("MINHASH");
if(mh != null) {
Collection col = mh.getValues();
List l = new ArrayList();
l.addAll(col);
fingerPrint.add("MINHASH", l);
if(id.contains("-")) {
long dbid = fetchDBID(id, responseBuilder.req.getSearcher());
if(dbid > -1) {
id = Long.toString(dbid);
} else {
id = null;
}
}
NamedList fingerPrint = new NamedList();
if(id != null) {
SolrInputDocument solrDoc = solrContentStore.retrieveDocFromSolrContentStore(AlfrescoSolrDataModel.getTenantId(TenantService.DEFAULT_DOMAIN), Long.parseLong(id));
if (solrDoc != null) {
SolrInputField mh = solrDoc.getField("MINHASH");
if (mh != null) {
Collection col = mh.getValues();
List l = new ArrayList();
l.addAll(col);
fingerPrint.add("MINHASH", l);
}
}
}
response.add("fingerprint", fingerPrint);
}
private long fetchDBID(String UUID, SolrIndexSearcher searcher) throws IOException {
String query = "workspace://SpacesStore/"+UUID;
TermQuery q = new TermQuery(new Term(QueryConstants.FIELD_LID, query));
TopDocs docs = searcher.search(q, 1);
Set<String> fields = new HashSet();
fields.add(QueryConstants.FIELD_DBID);
if(docs.totalHits == 1) {
ScoreDoc scoreDoc = docs.scoreDocs[0];
Document doc = searcher.doc(scoreDoc.doc, fields);
IndexableField dbidField = doc.getField(QueryConstants.FIELD_DBID);
return dbidField.numericValue().longValue();
}
return -1;
}
private SolrContentStore getContentStore(SolrQueryRequest req)
{
if(req.getSearcher() != null)
@@ -78,6 +78,7 @@ import org.alfresco.util.Pair;
import org.alfresco.util.SearchLanguageConversion;
import org.antlr.misc.OrderedHashSet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.lucene.search.*;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.commons.logging.Log;
@@ -99,17 +100,8 @@ import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.BooleanQuery.Builder;
import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MultiTermQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RegexpQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper;
import org.apache.lucene.search.spans.SpanMultiTermQueryWrapper.TopTermsSpanBooleanQueryRewrite;
import org.apache.lucene.search.spans.SpanNearQuery;
@@ -134,6 +126,7 @@ import org.apache.solr.handler.component.ShardHandlerFactory;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.update.DocumentBuilder;
import org.apache.solr.update.UpdateShardHandlerConfig;
import org.jaxen.saxpath.SAXPathException;
@@ -690,7 +683,7 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
{
String[] parts = queryText.split("_");
Collection values = null;
long nodeId = Long.parseLong(parts[0]);
String nodeId = parts[0];
JSONObject json = (JSONObject)request.getContext().get(AbstractQParser.ALFRESCO_JSON);
String fingerPrint = null;
@@ -712,13 +705,25 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
json = new JSONObject();
}
//Is the fingerprint in the local SolrContentStore
if(values == null) {
SolrInputDocument solrDoc = solrContentStore.retrieveDocFromSolrContentStore(AlfrescoSolrDataModel.getTenantId(TenantService.DEFAULT_DOMAIN), nodeId);
if (solrDoc != null) {
SolrInputField mh = solrDoc.getField("MINHASH");
if (mh != null) {
values = mh.getValues();
long dbid = -1;
//Do we have a UUID or DBID
if(nodeId.contains("-")) {
//It's a UUID. We need the DBID.
dbid = fetchDBID(nodeId);
} else {
dbid = Long.parseLong(nodeId);
}
if(dbid > -1) {
SolrInputDocument solrDoc = solrContentStore.retrieveDocFromSolrContentStore(AlfrescoSolrDataModel.getTenantId(TenantService.DEFAULT_DOMAIN), dbid);
if (solrDoc != null) {
SolrInputField mh = solrDoc.getField("MINHASH");
if (mh != null) {
values = mh.getValues();
}
}
}
}
@@ -728,6 +733,7 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
{
//we are in distributed mode
//Fetch the fingerPrint from the shards.
//The UUID and DBID will work both work for method call.
values = fetchFingerPrint(shards, nodeId);
}
@@ -772,7 +778,26 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
return builder.toString();
}
private Collection fetchFingerPrint(String shards, long nodeId) {
private long fetchDBID(String UUID) throws IOException {
SolrIndexSearcher searcher = request.getSearcher();
String query = UUID.startsWith("workspace") ? UUID : "workspace://SpacesStore/"+UUID;
TermQuery q = new TermQuery(new Term(FIELD_LID, query));
TopDocs docs = searcher.search(q, 1);
Set<String> fields = new HashSet();
fields.add(FIELD_DBID);
if(docs.totalHits == 1) {
ScoreDoc scoreDoc = docs.scoreDocs[0];
Document doc = searcher.doc(scoreDoc.doc, fields);
IndexableField dbidField = doc.getField(FIELD_DBID);
return dbidField.numericValue().longValue();
}
return -1;
}
private Collection fetchFingerPrint(String shards, String nodeId) {
shards = shards.replace(",", "|");
List<String> urls = ((HttpShardHandlerFactory)shardHandlerFactory).makeURLList(shards);
ExecutorService executorService = null;
@@ -781,7 +806,7 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
try {
executorService = Executors.newCachedThreadPool();
for (String url : urls) {
futures.add(executorService.submit(new FingerPrintFetchTask(url, Long.toString(nodeId))));
futures.add(executorService.submit(new FingerPrintFetchTask(url, nodeId)));
}
for (Future<Collection> future : futures) {
@@ -800,6 +825,8 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
}
private class FingerPrintFetchTask implements Callable<Collection> {
private String url;
private String id;
@@ -232,5 +232,72 @@ public class AlfrescoSolrFingerprintTest extends AbstractAlfrescoSolrTests
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
"//result/doc[4]/long[@name='DBID'][.='"+node1.getId()+"']");
//Test nodeRef
params = new ModifiableSolrParams();
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId()); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
params.add("qt", "/afts");
params.add("fl", "DBID,score");
params.add("start", "0");
params.add("rows", "6");
req = areq(params, null);
assertQ(req, "*[count(//doc)=4]",
"//result/doc[1]/long[@name='DBID'][.='" + node1.getId() + "']",
"//result/doc[2]/long[@name='DBID'][.='" + node3.getId() + "']",
"//result/doc[3]/long[@name='DBID'][.='" + node2.getId() + "']",
"//result/doc[4]/long[@name='DBID'][.='" + node4.getId() + "']");
params = new ModifiableSolrParams();
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId() + "_70"); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
params.add("qt", "/afts");
params.add("fl","DBID,score");
params.add("start", "0");
params.add("rows", "6");
req = areq(params, null);
assertQ(req, "*[count(//doc)= 2]",
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']");
params = new ModifiableSolrParams();
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId()+"_45"); //Query for an id in the content field. The node id is automatically populated into the content field by test framework
params.add("qt", "/afts");
params.add("fl","DBID,score");
params.add("start", "0");
params.add("rows", "6");
req = areq(params, null);
assertQ(req, "*[count(//doc)= 3]",
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']",
"//result/doc[3]/long[@name='DBID'][.='"+node2.getId()+"']");
params = new ModifiableSolrParams();
params.add("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId()+"_30");
params.add("qt", "/afts");
params.add("fl","DBID,score");
params.add("start", "0");
params.add("rows", "6");
req = areq(params, null);
assertQ(req, "*[count(//doc)= 4]",
"//result/doc[1]/long[@name='DBID'][.='"+node1.getId()+"']",
"//result/doc[2]/long[@name='DBID'][.='"+node3.getId()+"']",
"//result/doc[3]/long[@name='DBID'][.='"+node2.getId()+"']",
"//result/doc[4]/long[@name='DBID'][.='"+node4.getId()+"']");
params = new ModifiableSolrParams();
params.add("q", "FINGERPRINT:" + nodeMetaData4.getNodeRef().getId());
params.add("qt", "/afts");
params.add("fl","DBID,score");
params.add("start", "0");
params.add("rows", "6");
req = areq(params, null);
assertQ(req, "*[count(//doc)= 4]",
"//result/doc[1]/long[@name='DBID'][.='"+node4.getId()+"']",
"//result/doc[2]/long[@name='DBID'][.='"+node2.getId()+"']",
"//result/doc[3]/long[@name='DBID'][.='"+node3.getId()+"']",
"//result/doc[4]/long[@name='DBID'][.='"+node1.getId()+"']");
}
}
@@ -243,6 +243,77 @@ public class DistributedAlfrescoSolrFingerPrintTest extends AbstractAlfrescoDist
doc2 = docs.get(2);
dbid2 = (long)doc2.getFieldValue("DBID");
assertTrue(dbid2 == node2.getId());
response = query(getDefaultTestClient(), true,
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
params("q", "FINGERPRINT:"+nodeMetaData1.getNodeRef().getId(),
"qt", "/afts",
"shards.qt", "/afts",
"start", "0",
"fl","DBID,score",
"rows", "100"));
docs = response.getResults();
assertTrue(docs.getNumFound() == 4);
doc0 = docs.get(0);
dbid0 = (long)doc0.getFieldValue("DBID");
assertTrue(dbid0 == node1.getId());
doc1 = docs.get(1);
dbid1 = (long)doc1.getFieldValue("DBID");
assertTrue(dbid1 == node3.getId());
doc2 = docs.get(2);
dbid2 = (long)doc2.getFieldValue("DBID");
assertTrue(dbid2 == node2.getId());
doc3 = docs.get(3);
dbid3 = (long)doc3.getFieldValue("DBID");
assertTrue(dbid3 == node4.getId());
response = query(getDefaultTestClient(), true,
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
params("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId() +"_70",
"qt", "/afts",
"shards.qt", "/afts",
"start", "0",
"fl", "DBID,score",
"rows", "100"));
docs = response.getResults();
assertTrue(docs.getNumFound() == 2);
doc0 = docs.get(0);
dbid0 = (long)doc0.getFieldValue("DBID");
assertTrue(dbid0 == node1.getId());
doc1 = docs.get(1);
dbid1 = (long)doc1.getFieldValue("DBID");
assertTrue(dbid1 == node3.getId());
response = query(getDefaultTestClient(), true,
"{\"locales\":[\"en\"], \"templates\": [{\"name\":\"t1\", \"template\":\"%cm:content\"}], \"authorities\": [\"joel\"], \"tenants\": []}",
params("q", "FINGERPRINT:" + nodeMetaData1.getNodeRef().getId() +"_45",
"qt", "/afts",
"shards.qt", "/afts",
"start", "0",
"fl", "DBID,score",
"rows", "100"));
docs = response.getResults();
assertTrue(docs.getNumFound() == 3);
doc0 = docs.get(0);
dbid0 = (long)doc0.getFieldValue("DBID");
assertTrue(dbid0 == node1.getId());
doc1 = docs.get(1);
dbid1 = (long)doc1.getFieldValue("DBID");
assertTrue(dbid1 == node3.getId());
doc2 = docs.get(2);
dbid2 = (long)doc2.getFieldValue("DBID");
assertTrue(dbid2 == node2.getId());
}
}