Most of us would have used the typeahead feature in different software systems. In today’s post we will look into type-ahead using Oracle Endeca dimension search.
Different approaches to do type-ahead in Oracle Endeca.
- Dimension Keyword Search.
- Record Keyword Search.
- Dimension Keyword Search combined with predefined set of tokens.
- Dimension Keyword Search combined with search logs.
- Dimension Keyword Search combined with taxonomy synonyms.
There is no best approach or bad approach as per my experience. Its all depends on your application, targeted user base and requirements. In our example we are using dimension keyword search. Since we are using dimension keyword search the auto-complete/type-ahead/suggestion tokens would come from the dimension/taxonomy tree.
Tools and Libraries used.
Java program to fetch taxonomy with it’s ancestors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
package com.ourownjava.endeca; import java.util.ArrayList; import java.util.List; import com.endeca.navigation.DimLocation; import com.endeca.navigation.DimLocationList; import com.endeca.navigation.DimVal; import com.endeca.navigation.DimValList; import com.endeca.navigation.DimensionSearchResult; import com.endeca.navigation.DimensionSearchResultGroup; import com.endeca.navigation.DimensionSearchResultGroupList; import com.endeca.navigation.ENEQuery; import com.endeca.navigation.ENEQueryException; import com.endeca.navigation.ENEQueryResults; import com.endeca.navigation.HttpENEConnection; /** * Oracle Endeca — Type-ahead using dimension search. * * @author ourownjava.com */ public class TypeAheadWithAncestors { @SuppressWarnings({ "static-method" }) private ENEQueryResults search(final ENEQuery eneQuery) throws ENEQueryException { return new HttpENEConnection("localhost", "15000").query(eneQuery); } /** * This method shall return suggestion list with ancestors from the dimension tree. * * @param dimensionName * @return DimensionWrapper * @throws ENEQueryException */ public List<String> findRelatedTokens(final String dimensionName) throws ENEQueryException { final List<String> tokens = new ArrayList<String>(); final ENEQuery query = new ENEQuery(); query.setDimSearchTerms(dimensionName); query.setNavERecSearchComputeAlternativePhrasings(true); final ENEQueryResults results = search(query); final DimensionSearchResult dimensionSearchResult = results.getDimensionSearch(); final DimensionSearchResultGroupList dimensionSearchResultGroupList = dimensionSearchResult.getResults(); for (Object dimensionSearchResultGroupElement : dimensionSearchResultGroupList) { final DimensionSearchResultGroup dimensionSearchResultGroup = (DimensionSearchResultGroup) dimensionSearchResultGroupElement; final DimValList roots = dimensionSearchResultGroup.getRoots(); if (roots.size() != 0) { StringBuilder token = new StringBuilder(); final DimVal root = (DimVal) roots.get(0); if(!"product.category".equalsIgnoreCase(root.getDimensionName())){ token.append(root.getDimensionName()); token.append("> "); } for (int i = 0; i < dimensionSearchResultGroup.size(); i++) { final DimLocationList dimLocationList = (DimLocationList) dimensionSearchResultGroup.get(i); for (Object dimLocationElement : dimLocationList) { final DimLocation dimLocation = (DimLocation) dimLocationElement; final DimValList ancestors = dimLocation.getAncestors(); for (Object dimValElement : ancestors) { final DimVal dimVal = (DimVal) dimValElement; token.append(dimVal.getName()); token.append("> "); } final DimVal dimVal = dimLocation.getDimValue(); token.append(dimVal.getName()); token.append("\n"); } } tokens.add(token.toString()); } } return tokens; } } |
Test code for the above listed program.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.ourownjava.endeca.test; import static org.junit.Assert.assertTrue; import java.util.List; import org.junit.Before; import org.junit.Test; import com.endeca.navigation.ENEQueryException; import com.ourownjava.endeca.TypeAheadWithAncestors; /** * * @author ourownjava.com * */ public class TypeAheadWithAncestorsBehavior { private TypeAheadWithAncestors typeAheadWithAncestors; @Before public void setUp(){ typeAheadWithAncestors = new TypeAheadWithAncestors(); } @Test public void shouldFindTypeAheadEntries() throws ENEQueryException{ final List tokens = typeAheadWithAncestors.findRelatedTokens("Back"); assertTrue(tokens.size() > 0); tokens.contains("camera"); } } |
Client JSP code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!-- @author ourownjava.com --> <%@page import="java.util.Iterator"%> <%@page import="java.util.List"%> <%@page import="com.ourownjava.endeca.TypeAheadWithAncestors"%> <% TypeAheadWithAncestors typeAheadWithAncestors = new TypeAheadWithAncestors(); String query = request.getParameter("q"); List tokens = typeAheadWithAncestors.findRelatedTokens("*"+query.toLowerCase() +"*"); Iterator iterator = tokens.iterator(); while(iterator.hasNext()) { String token = (String)iterator.next(); out.println(token); } %> |
Screen shot of typeahead.
Complete Source Code in Git.
Hi ,
Dimension Keyword Search vs Keyword Search Query uisng presentation API . real time scenario pls and can u pls through some lights on ASSEMPLER API pls…
hi Bala, Thanks for looking into this post. The difference between dimension keyword search and record keyword search is available in https://ourownjava.com/endeca/oracle-endeca-query-types-2/. I will be writing about oracle endeca content assembler api in the coming weeks.
Hi,
Thank you for your post.
I would like to know , what is the use of the java file “OracleEndecaDimensionSearchClient”.
Also, how the MDEX engine indexing done for this type ahead.
Ok… I found the other blog “https://ourownjava.com/endeca/oracle-endeca-load-dimension-tree-dimension-search/ ” which refers to “OracleEndecaDimensionSearchClient”
Regarding my question on MDEX engine, I hope it is using the sample app, say Discover, deployed to MDEX.
hi Sony, Yes, I have used the sample discover application.
Hi,
In the above scenario the typed word is code and getting results for that. It is returning the results for code in the middle of the string. Is it possible to get results starting with code? What changes i need to make to get the typeahead values present only at starting of the string and not at the middle.
Hi,
When we use Dimension Keyword Search for type ahead, can we get search in multiple dimensions and get the most relevant ones from all the dimensions selected. The problem is , Endeca auto suggest catridge has a field “maximum entries per dimension”, which is restricting the suggestions from dimensions. Can we somehow override this property ?