private static final String assocIndex_ = AssociationFeaturePojoIndexMap.indexCollectionName_ + "/" + AssociationFeaturePojoIndexMap.indexName_;
public ResponsePojo getAssociationSuggestions(String userIdStr, String ent1, String verb, String ent2, String field, String communityIdStrList, boolean bWantNoAlias)
{
ResponsePojo rp = new ResponsePojo();
try
{
// Community ids, needed in a couple of places
String[] communityIdStrs = SocialUtils.getCommunityIds(userIdStr, communityIdStrList);
// Initial alias handling:
AliasLookupTable aliasTable = null;
// Initial alias handling:
if (!bWantNoAlias) {
AliasManager aliasManager = AliasManager.getAliasManager();
if (null != aliasManager) {
aliasTable = aliasManager.getAliasLookupTable(communityIdStrList, communityIdStrs, null, userIdStr);
}
}//TESTED
ElasticSearchManager esm = ElasticSearchManager.getIndex(assocIndex_);
SearchRequestBuilder searchOptions = esm.getSearchOptions();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolean bExtraQueryTerms = false;
String term = "";
if ( !ent1.equals("null") )
{
if ( field.equals(AssociationFeaturePojo.entity1_) )
term = ent1;
else {
bExtraQueryTerms = true;
EntityFeaturePojo alias = null;
if (null != aliasTable) {
alias = aliasTable.getAliasMaster(ent1);
}
if (null != alias) { // Found!
boolQuery.must(QueryBuilders.termsQuery(AssociationFeaturePojo.entity1_index_, alias.getAlias().toArray()));
}
else {
boolQuery.must(QueryBuilders.termQuery(AssociationFeaturePojo.entity1_index_, ent1));
}//TESTED
}
}
if ( !verb.equals("null") )
{
if ( field.equals(AssociationFeaturePojo.verb_) )
term = verb;
else
{
bExtraQueryTerms = true;
boolQuery.must(QueryBuilders.queryString(new StringBuffer("+").append(verb.replaceAll("\\s+", " +")).toString()).
defaultField(AssociationFeaturePojo.verb_));
}
}
if ( !ent2.equals("null") )
{
if ( field.equals(AssociationFeaturePojo.entity2_) )
term = ent2;
else {
bExtraQueryTerms = true;
EntityFeaturePojo alias = null;
if (null != aliasTable) {
alias = aliasTable.getAliasMaster(ent2);
}
if (null != alias) { // Found!
boolQuery.must(QueryBuilders.termsQuery(AssociationFeaturePojo.entity2_index_, alias.getAlias().toArray()));
}
else {
boolQuery.must(QueryBuilders.termQuery(AssociationFeaturePojo.entity2_index_, ent2));
}
}//TESTED (cut and paste from entity1)
}
String escapedterm = null;
StandardTokenizer st = new StandardTokenizer(Version.LUCENE_30, new StringReader(ContentUtils.stripDiacritics(term)));
CharTermAttribute termAtt = st.addAttribute(CharTermAttribute.class);
StringBuffer sb = new StringBuffer();
try {
try {
st.reset();
while (st.incrementToken()) {
if (sb.length() > 0) {
sb.append(" +");
}
else {
sb.append('+');
}
sb.append(luceneEncodeTerm(termAtt.toString()));
}
}
finally {
st.close();
}
} catch (IOException e) {
e.printStackTrace();
}
if (!term.endsWith(" ") || (0 == sb.length())) { // Could be in the middle of typing, stick a * on the end
sb.append('*');
}//TESTED
escapedterm = sb.toString();
// Also create an internal Lucene index for aliases, in case any of them do not have actual entities representing them
List<EntityFeaturePojo> extraEntries = null;
BoolQueryBuilder extraQueryTerms = null;
if (field.startsWith("entity")) {
String indexField = field.startsWith("entity1") ? "entity1_index" : "entity2_index";
if (null != aliasTable) {
extraEntries = checkAliasMasters(aliasTable, escapedterm);
}
if (null != extraEntries) {
extraQueryTerms = QueryBuilders.boolQuery();
int nExtraTerms = 0;
Iterator<EntityFeaturePojo> aliasIt = extraEntries.iterator();
while (aliasIt.hasNext()) {
EntityFeaturePojo alias = aliasIt.next();
nExtraTerms += alias.getAlias().size();
if (!bExtraQueryTerms && (nExtraTerms > 20)) { // If not filtering on event type we'll be more aggressive
break;
}//TESTED
if (bExtraQueryTerms && (nExtraTerms > 60)) { // If the number of terms gets too large bail anyway
break;
}//TESTED
extraQueryTerms.should(QueryBuilders.termsQuery(indexField, alias.getAlias().toArray()));
aliasIt.remove();
}//end loop over entities
}//if found new aliases
}//(if this is an entity lookup) TESTED - including breaking out because of # of terms
// (end initial alias handling)
if (null == extraQueryTerms) {
boolQuery.must(QueryBuilders.queryString(escapedterm).defaultField(field));
}
else {//(in this case combine the escaped term with the aliases
extraQueryTerms.should(QueryBuilders.queryString(escapedterm).defaultField(field));
boolQuery.must(extraQueryTerms);
}//TESTED
boolQuery.must(QueryBuilders.termsQuery(AssociationFeaturePojo.communityId_, communityIdStrs));
searchOptions.addSort(AssociationFeaturePojo.doccount_, SortOrder.DESC);
// Work out which fields to return:
//TODO (INF-1234) need to work out what to do with quotations and similar here (ie entityX without entityX_index)
String returnfield;
boolean bReturningEntities = true;
if ( field.equals(AssociationFeaturePojo.entity1_) ) {
returnfield = AssociationFeaturePojo.entity1_index_;
searchOptions.addFields( AssociationFeaturePojo.entity1_index_, AssociationFeaturePojo.doccount_);
}
else if ( field.equals(AssociationFeaturePojo.entity2_)) {
returnfield = AssociationFeaturePojo.entity2_index_;
searchOptions.addFields( AssociationFeaturePojo.entity2_index_, AssociationFeaturePojo.doccount_);
}
else {
bReturningEntities = false;
returnfield = AssociationFeaturePojo.verb_;
searchOptions.addFields( AssociationFeaturePojo.verb_, AssociationFeaturePojo.verb_category_, AssociationFeaturePojo.doccount_);
}
int nNumSuggestionsToReturn = 20;
if (bReturningEntities && (null != aliasTable)) {
searchOptions.setSize(3*nNumSuggestionsToReturn); // we're going to remove some duplicates so get more than we need
}
else { // normal case
searchOptions.setSize(nNumSuggestionsToReturn);
}
SearchResponse rsp = esm.doQuery(boolQuery, searchOptions);
SearchHit[] docs = rsp.getHits().getHits();
//Currently this code takes the results and puts
//them into a set so there are no duplicates
//duplicates occur for example when you search for
//obama you get obama/quotation/quote1 and obama/travel/spain
//may want to work this differnt, or atleast sum up
//frequency
Set<String> suggestions = new HashSet<String>();
for (SearchHit hit: docs)
{
SearchHitField retField = hit.field(returnfield); // (this can be null in theory/by mistake)
if (null != retField) {
String suggestion = (String) retField.value();
if (bReturningEntities && (null != aliasTable))
{
// More alias handling
EntityFeaturePojo alias = aliasTable.getAliasMaster(suggestion);
if (null != alias) { // Found!
if (alias.getIndex().equalsIgnoreCase("discard")) { // Discard this entity
continue;
}
else {
// (these need to be present)
suggestion = alias.getIndex();
}
}//TESTED
}
else { // (old code, still valid for verbs or no aliases)
if ( returnfield.equals(AssociationFeaturePojo.verb_) && hit.field(AssociationFeaturePojo.verb_category_) != null )
//for some reason verb_cat can be null!?!?! i think this is broken (ent1 facebook inc/company verb *)
{
String verbcat = (String)hit.field(AssociationFeaturePojo.verb_category_).value();
suggestion += " (" + verbcat + ")";
suggestions.add(verbcat);
}
}
suggestions.add(suggestion);
if (suggestions.size() >= nNumSuggestionsToReturn) {
break;
}
} // (end return string valid)
}//end loop over suggestions
// Add any aliases that I couldn't explicity convert to query terms
if ((null != extraEntries) && (suggestions.size() < nNumSuggestionsToReturn)) {
for (EntityFeaturePojo alias: extraEntries) {
suggestions.add(alias.getIndex());
if (suggestions.size() >= nNumSuggestionsToReturn) {
break;
}
}
}//(end add any remaining entries)
//TESTED
String[] suggestionArray = new String[suggestions.size()];
rp.setData(Arrays.asList(suggestions.toArray(suggestionArray)), (BasePojoApiMap<String>)null);
String searchTerm = "";
if ( field.equals(AssociationFeaturePojo.entity1_))
searchTerm = ent1;
else if ( field.equals(AssociationFeaturePojo.verb_))
searchTerm = verb;
else
searchTerm = ent2;
rp.setResponse(new ResponseObject("Association Suggestions", true, searchTerm));
}
catch (Exception ex)
{
ex.printStackTrace();
rp.setResponse(new ResponseObject("Association Suggestions",false,"Response returned unsuccessfully: " + ex.getMessage()));
}
return rp;
}