Message Boards
Leveraging search vs search and indexing
Tiago Machado, modified 6 Years ago.
Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
Good morning everyone!
I am trying to do a simple search, and for that I am following the guestbook tutorial.
I first found the "Leveragin Search" : https://dev.liferay.com/es/develop/tutorials/-/knowledge_base/7-0/leveraging-search
And that is what I followed, but since I was getting a null at
so, I searched a little for and foun the "Search and Indexing" : https://dev.liferay.com/es/develop/tutorials/-/knowledge_base/7-1/search-and-indexing
What is the diference? I readed but I couldn't fully understand, it seems a lot more complex.
I'm still trying to understand the Leveraging search, that should work for what I want for now.
Since I'm my hit.getDocs is alwyas null i guess the problem is in the doGetDocument?
Thank you all for your time.
I am trying to do a simple search, and for that I am following the guestbook tutorial.
I first found the "Leveragin Search" : https://dev.liferay.com/es/develop/tutorials/-/knowledge_base/7-0/leveraging-search
And that is what I followed, but since I was getting a null at
Hits hits = indexer.search(searchContext);
List<movie> movies = new ArrayList<movie>();
System.out.println("hitsDocsLength " + hits.getDocs().length);
for (int i = 0 ; i < hits.getDocs().length ; i++ ) {</movie></movie>
The length is always 0, and well, wont enter the for, and the search results is always "no movies found"so, I searched a little for and foun the "Search and Indexing" : https://dev.liferay.com/es/develop/tutorials/-/knowledge_base/7-1/search-and-indexing
What is the diference? I readed but I couldn't fully understand, it seems a lot more complex.
I'm still trying to understand the Leveraging search, that should work for what I want for now.
Since I'm my hit.getDocs is alwyas null i guess the problem is in the doGetDocument?
@Override
protected Document doGetDocument(Movie movie) throws Exception {
Document document = getBaseModelDocument(CLASS_NAME, movie);
document.addDate(Field.MODIFIED_DATE, movie.getModifiedDate());
document.addText("movieName", movie.getMovieName());
document.addText("description", movie.getDescription());
document.addNumber("rating", movie.getRating());
document.addText("authorName", movie.getAuthor().getAuthorName());
Locale defaultLocale = PortalUtil.getSiteDefaultLocale(movie.getGroupId());
String localizedTitle = LocalizationUtil.getLocalizedName(Field.TITLE, defaultLocale.toString());
String localizedMessage = LocalizationUtil.getLocalizedName(Field.CONTENT, defaultLocale.toString());
document.addText(localizedTitle, movie.getMovieName());
document.addText(localizedMessage, movie.getDescription());
return document;
}
Am I doing something wrong there?Thank you all for your time.
David H Nebinger, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Liferay Legend Posts: 14931 Join Date: 9/2/06 Recent Posts
Not necessarily...
First I'd connect to your search service directly. Do your own queries, make sure the records are in there.
The easy case is that they are not in there and you're not (or haven't yet) indexed the records. This could point to either needing to reindex or, worst case, there is an issue w/ your index code in that it is not being added to the index.
If your data is in there, then you have to check out your queries. Debug your way through a search and see what is getting generated and how the search is actually being processed.
First I'd connect to your search service directly. Do your own queries, make sure the records are in there.
The easy case is that they are not in there and you're not (or haven't yet) indexed the records. This could point to either needing to reindex or, worst case, there is an issue w/ your index code in that it is not being added to the index.
If your data is in there, then you have to check out your queries. Debug your way through a search and see what is getting generated and how the search is actually being processed.
Tiago Machado, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
Hey David, thanks for the answer!
I'm really trying hard, I'm trying for two days but no luck
I tryed another method that I saw from a video, I understood much better the logic but again, not entering the for, so like you said I think my entries are not being Indexed right?
Here is the code from my class:
In my Impl I have my addMovie, addMovieAndAuthor, update and delete with the @Indexable
I don't really understand, with that piece of code I should get something right? well, at least in the video I saw it was working, even so it was 6.2...
that BooleanQuery is deprecated, what does that mean btw?
Thank you for your time!
I'm really trying hard, I'm trying for two days but no luck

I tryed another method that I saw from a video, I understood much better the logic but again, not entering the for, so like you said I think my entries are not being Indexed right?
Here is the code from my class:
@Component(
immediate = true,
property = {
"javax.portlet.name=" + MoviesPortletKeys.MOVIES,
"MVC.command.name=" + MVCCommandNames.SEARCH_MOVIES,
},
service = MVCActionCommand.class
)
public class SearchMoviesMVCAtionCommand extends BaseMVCActionCommand {
@Override
protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse) throws Exception {
String keyword = ParamUtil.getString(actionRequest, "keyword");
System.out.println("keyword: " + keyword);
SearchContext searchContext = SearchContextFactory.getInstance(PortalUtil.getHttpServletRequest(actionRequest));
BooleanQuery searchQuery = BooleanQueryFactoryUtil.create(searchContext);
searchQuery.addRequiredTerm(Field.ENTRY_CLASS_NAME, Movie.class.getName());
searchQuery.addRequiredTerm(Field.TITLE, keyword);
//searchQuery.addRequiredTerm("head", Boolean.TRUE);
try {
Hits hits = SearchEngineUtil.search(searchContext, searchQuery);
List<document> docList = hits.toList();
for (Document document : docList) {
System.out.println("Movie id: " + document.get("movieId"));
System.out.println("Content: " + document.get(Field.CONTENT));
}
} catch (SearchException e) {
e.printStackTrace();
}
}
}</document>
In the JSP I just have that: <portlet:actionurl var="searchURL" name="<%=MVCCommandNames.SEARCH_MOVIES %>" />
<aui:form action="<%=searchURL %>" methos="POST">
<aui:input name="keyword" label="Search Movie" />
<aui:button type="submit" value="search" />
</aui:form>
I just wanted to test if im getting the data im looking for, but im not, the only thing that im getting is the keyword I search for.In my Impl I have my addMovie, addMovieAndAuthor, update and delete with the @Indexable
I don't really understand, with that piece of code I should get something right? well, at least in the video I saw it was working, even so it was 6.2...
that BooleanQuery is deprecated, what does that mean btw?
Thank you for your time!
Tiago Machado, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
Hello again, I kinda resolved the problem, well, not with the Indexer, instead I searched an found a solution, but im having some issue, and I have a question too.
I found the following solution: https://liferayiseasy.blogspot.com/2017/09/liferay-search-form-with-search.html
I needed to make an ajustment so it would search(keep in the same jsp) instead of going to the main view when I searched for something.
That was the solution I used for my search, but I'm having a problem.
But even if it works that way, im getting "[DynamicQueryFactoryImpl:103] Unable find model com.liferay.training.movies.model.impl.MovieImpl"
As you can see in the link I gave you, instead of the PortletClassLoaderUtil, he is using ClpSerialized, but I don't know why, but I can't import it...
Also, I have read the following topic : https://community.liferay.com/forums/-/message_boards/message/86478400?_com_liferay_message_boards_web_portlet_MBPortlet_showBreadcrumb=false
For what I have read there, the MovieHelper class (Employee Helper in the tutorial link) should be in the MovieLocalServiceImpl is that right? but what about the DisplayTerms class? where should I put it?
sorry and thanks for the help
I found the following solution: https://liferayiseasy.blogspot.com/2017/09/liferay-search-form-with-search.html
I needed to make an ajustment so it would search(keep in the same jsp) instead of going to the main view when I searched for something.
That was the solution I used for my search, but I'm having a problem.
ClassLoader classLoader = (ClassLoader) PortletBeanLocatorUtil.locate(
PortletClassLoaderUtil.getServletContextName(), "portletClassLoader");
DynamicQuery dynamicQuery = DynamicQueryFactoryUtil.forClass(Movie.class, "movie", classLoader);
For it to work I had to comment the classLoader, and remove the classLoader argument, or I would get "No servlet context name specified"But even if it works that way, im getting "[DynamicQueryFactoryImpl:103] Unable find model com.liferay.training.movies.model.impl.MovieImpl"
As you can see in the link I gave you, instead of the PortletClassLoaderUtil, he is using ClpSerialized, but I don't know why, but I can't import it...
Also, I have read the following topic : https://community.liferay.com/forums/-/message_boards/message/86478400?_com_liferay_message_boards_web_portlet_MBPortlet_showBreadcrumb=false
For what I have read there, the MovieHelper class (Employee Helper in the tutorial link) should be in the MovieLocalServiceImpl is that right? but what about the DisplayTerms class? where should I put it?
sorry and thanks for the help
David H Nebinger, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Liferay Legend Posts: 14931 Join Date: 9/2/06 Recent Posts
You should not use DQFUtil, there is no reason to.
You can just invoke _movieLocalService.dynamicQuery() (no arguments) to create a new DQ instance that you can populate. Takes all of the hassle of working w/ the class loaders out of the picture.
The detailed response is that you are trying to use the portlet's class loader when the necessary DQ class loader comes from the service module.
If you use the dynamicQuery() method, all of this is taken care of for you.
You can just invoke _movieLocalService.dynamicQuery() (no arguments) to create a new DQ instance that you can populate. Takes all of the hassle of working w/ the class loaders out of the picture.
The detailed response is that you are trying to use the portlet's class loader when the necessary DQ class loader comes from the service module.
If you use the dynamicQuery() method, all of this is taken care of for you.
Tiago Machado, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
Thank you very much David!!!
Worked perfectly.
can't thank you enough for you help!!!
THANKS!
Have a nice day!!
Worked perfectly.
can't thank you enough for you help!!!
THANKS!
Have a nice day!!

Tiago Machado, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
hey David, just one more thing, I was testing around, and actually found that my MovieDisplayTerms wasn't really doing anything, so I removed it and changed the arguments where I was using to just the DisplayTerms. Is that ok?
And btw, im searching using the Movie properties, for example if I search a movie name or rating it will show that movie in the search container including the author, but what if i want to search using the authorName too? is it posible to join DynamicQueries? or should I create another class for that author query search?
thanks for your time!
And btw, im searching using the Movie properties, for example if I search a movie name or rating it will show that movie in the search container including the author, but what if i want to search using the authorName too? is it posible to join DynamicQueries? or should I create another class for that author query search?
thanks for your time!
David H Nebinger, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Liferay Legend Posts: 14931 Join Date: 9/2/06 Recent Posts
if you don't need a custom movie display terms, don't use one.
For the search, a search happens on the indexed document, not on the database.
So this means that when you are building the document to store in the index, you're populating w/ fields from the movie. If you also populate the author details, you can search to find movies based on author.
Note that this search returns movies, not authors, you'd have your other index class if you needed to index authors, and that searcher would support searching for a list of authors.
For the search, a search happens on the indexed document, not on the database.
So this means that when you are building the document to store in the index, you're populating w/ fields from the movie. If you also populate the author details, you can search to find movies based on author.
Note that this search returns movies, not authors, you'd have your other index class if you needed to index authors, and that searcher would support searching for a list of authors.
Tiago Machado, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
Hey David, thanks for the answer, since I wasn't able to figure out the issue with my indexer, (for some reason I think the records wans't being indexed) tried a lot of things so I found a solution, but not using the Indexer, instead I did that:
is that ok to do? or should I find other way?
thanks!
public class MovieHelper {
public static List<movie> getMovie(DisplayTerms displayTerms, int start, int end) throws SystemException {
List<movie> movieList = getMovieData(displayTerms.isAdvancedSearch(), displayTerms.isAndOperator(),
displayTerms.getKeywords());
return ListUtil.subList(movieList, start, end);
}
public static int getTotalMovieCount(DisplayTerms displayTerms, int start, int end) throws SystemException {
return getMovieData(displayTerms.isAdvancedSearch(), displayTerms.isAndOperator(),
displayTerms.getKeywords()).size();
}
public static List<movie> getMovieData(boolean isAdvancedSearch, boolean isAndOperator, String keywords) throws SystemException {
List<movie> movieList = Collections.EMPTY_LIST;
List<movie> moviesListQueriedAndSettedAuthorsList = Collections.EMPTY_LIST;
if ((Validator.isBlank(keywords)) && (!isAdvancedSearch)) {// No search
movieList = MovieLocalServiceUtil.getMovies(0, MovieLocalServiceUtil.getMoviesCount());
moviesListQueriedAndSettedAuthorsList = MovieLocalServiceUtil.getMoviesAndAuthors(0,
MovieLocalServiceUtil.getMoviesCount());
} else {
DynamicQuery dynamicQuery = MovieLocalServiceUtil.dynamicQuery();
Junction junction = null;
if (isAdvancedSearch) {// Advanced Search
if (isAndOperator) {
System.out.println("All means And");
junction = RestrictionsFactoryUtil.conjunction();
}
else {
System.out.println("Any means OR");
junction = RestrictionsFactoryUtil.disjunction();
}
junction.add(PropertyFactoryUtil.forName("movieId").eq(Long.valueOf(keywords)));
junction.add(PropertyFactoryUtil.forName("rating").eq(Integer.valueOf(keywords)));
junction.add(PropertyFactoryUtil.forName("movieName").like("%" + keywords + "%"));
junction.add(PropertyFactoryUtil.forName("rating").like("%" + keywords + "%"));
}
else {// Normal Search
junction = RestrictionsFactoryUtil.disjunction();
if (Validator.isDigit(keywords)) {
junction.add(PropertyFactoryUtil.forName("movieId").eq(Long.valueOf(keywords)));
junction.add(PropertyFactoryUtil.forName("rating").eq(Integer.valueOf(keywords)));
}
junction.add(PropertyFactoryUtil.forName("movieName").like("%" + keywords + "%"));
}
dynamicQuery.add(junction);
movieList = MovieLocalServiceUtil.dynamicQuery(dynamicQuery);
//invokes the method that will set the queried movies to set the movies the respective author
moviesListQueriedAndSettedAuthorsList = MovieLocalServiceUtil.getMoviesAndAuthorsQueried(movieList);
}
return moviesListQueriedAndSettedAuthorsList;
}
}</movie></movie></movie></movie></movie>
I'm still using the DisplayTerms, but not with the MovieDisplayTerms class, since it was doing nothing I removed it and adapted the code.is that ok to do? or should I find other way?
thanks!
David H Nebinger, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Liferay Legend Posts: 14931 Join Date: 9/2/06 Recent Posts
This code has problems...
Imagine your database has 2 million movies loaded and user ends up calling:
So first you're just trying to cast the keywords to integers, longs, etc. Users don't typically search by ID (ID is an internal field that users will never know).
Rating is typically a filter, not a search, because the rating is not typically indexed because it changes with each review (there is no single rating, if I rate 5 and you rate 1, the average rating for the movie should be a 3).
Now for the nasty part...
Your movie has 2 million records, but you are completely ignoring the "0, 5" window as part of the query. So you're going to do a database query where name is '%e%'. Given that the letter e is the most prevalent letter used in the alphabet, it may not pull all 2 million records, but it may be close. So you're going to pull all of the records in order to take the first 5 and discard the rest?
Lastly, there are things that you haven't considered. Your query appears to be case-sensitive, so if I search for 'e' vs 'E', I'm going to get different results.
Also keywords is not apparently key words because if I enter "house cat", you're only going to be searching for an exact phrase match of '%house cat%' and exclude movies that match on house, cat, "cat house" (because of order), etc. And, if I do something like "house cat", I'll never find anything because no title will have all of those spaces between the words.
There's a reason why we use the search index and not just write our own search services. Search is hard. It is hard to get things right even on "happy path" search queries, but it is practically impossible to correctly handle all of the edge cases.
Your code above might pass some "happy path" testing as long as it is not too vigorous, but the first real usage of this in a production system would break miserably and likely require a top-down rewrite in order to use the index correctly.
Imagine your database has 2 million movies loaded and user ends up calling:
DisplayTerms dt = ...
dt.setKeywords("e");
...
List<movie> movies = movieHelper.getMovie(dt, 0, 5);</movie>
So first you're just trying to cast the keywords to integers, longs, etc. Users don't typically search by ID (ID is an internal field that users will never know).
Rating is typically a filter, not a search, because the rating is not typically indexed because it changes with each review (there is no single rating, if I rate 5 and you rate 1, the average rating for the movie should be a 3).
Now for the nasty part...
Your movie has 2 million records, but you are completely ignoring the "0, 5" window as part of the query. So you're going to do a database query where name is '%e%'. Given that the letter e is the most prevalent letter used in the alphabet, it may not pull all 2 million records, but it may be close. So you're going to pull all of the records in order to take the first 5 and discard the rest?
Lastly, there are things that you haven't considered. Your query appears to be case-sensitive, so if I search for 'e' vs 'E', I'm going to get different results.
Also keywords is not apparently key words because if I enter "house cat", you're only going to be searching for an exact phrase match of '%house cat%' and exclude movies that match on house, cat, "cat house" (because of order), etc. And, if I do something like "house cat", I'll never find anything because no title will have all of those spaces between the words.
There's a reason why we use the search index and not just write our own search services. Search is hard. It is hard to get things right even on "happy path" search queries, but it is practically impossible to correctly handle all of the edge cases.
Your code above might pass some "happy path" testing as long as it is not too vigorous, but the first real usage of this in a production system would break miserably and likely require a top-down rewrite in order to use the index correctly.
Tiago Machado, modified 6 Years ago.
RE: Leveraging search vs search and indexing
Junior Member Posts: 59 Join Date: 2/21/19 Recent Posts
Thank you for the answer David, I understand and I will try to fix this and use the Indexer!
Thank you very much
Thank you very much
