Letzte Blogger

Geert van der Ploeg

1 Nachrichten
20. September 2016

Olaf Kock

Staff
117 Nachrichten
20. September 2016

Antonio Pol

Staff
1 Nachrichten
19. September 2016

David H Nebinger

31 Nachrichten
15. September 2016

Javeed Chida

11 Nachrichten
15. September 2016

Jan Eerdekens

13 Nachrichten
14. September 2016

Nate Cavanaugh

Staff
39 Nachrichten
12. September 2016

Maarten van Heiningen

2 Nachrichten
5. September 2016

Melanie Chung

Staff
5 Nachrichten
2. September 2016

Neil Griffin

Staff
55 Nachrichten
2. September 2016
« Zurück

Faceted Search in Liferay 6.1

Company Blogs 9. März 2012 Von Ray Augé Staff

It's been so long since I've written anything, I've been fealing rather guilty. Luckly recently we've been undertaking a huge effort to document features of Liferay, old and new.

One interesting but highly understated feature of Liferay 6.1 is the new Faceted Search support that I was lucky enough to get to work on. As I finished the first round of documentation (for my more eloquent peers to turn into a more polished and finished product) I thought that this would be a great bunch of info to place here for comment. It's a little more formal than a blog post should be, and probably much longer as well (there is even a toc!!!).. but what the hey!

 

Definitions

Before going through features, let us outline a set of definitions that are commonly used in discussion Faceted Search (or search in general).

indexed field: When we store documents in a search engine, we classify aspects of the document into fields. These fields represent the metadata about each document. Some typical fields are: name, creation date, author, type, tags, content, etc.

term : A term is a single value that can be searched which does not contain any whitespace characters. Terms may appear more than once in a document or appear in several documents, and are typically considered atomic units of search. Within the search engine, each indexed field (for example name) will have a list of known terms found within all the documents having that particular indexed field.

phrase: A phrase is a series of terms separated by spaces. The only way to use a phrase as a term in a search is to surround it with double quotes (").

multi value field: Some fields store more than one term at a time. For instance the "content" field may in fact contain hundreds of unique terms. Such fields are often referred to as "text" or "array" fields.

single value field: In contrast to multi-value fields, we have to logically assume that there is such a thing as single value field. Such fields always only contain a single term. These fields are often referred to as "token" or "string" fields.

frequency: The frequency value indicates how many times a term appears within a set of documents.

facet: A facet is a combination of the information about a specific indexed field, it's terms and their frequency. Facets are typically named by the field in question.

term result list: When a facet displays it's data, we call this the term result list.

frequency threshold: Some facet have a property called frequency threshold. This value indicates the minimum number for frequency of terms we want to show. If the frequency threshold of a facet is set to 1, a term appearing 1 or more times will appear in the term result list.

max terms: Some facet have a property called max terms. This value indicates the maximum number of terms that will be included in the term result list regardless of how many actual matching terms are found for the facet. This is done to keep the user interface under control and not to overwhelm the user with too much information.

order: The order property determines the default ordering used for the term result list. There are two possible modes: Order Hits Descending, or Order Value Ascending. The first, Order Hits Descending , means that results will be ordered by frequency in a descending order. The second, Order Value Ascending, means that the results will be ordered by value (i.e. "term") in ascending order. Both modes will fall back to the other mode as a secondary sort order when there are duplicates. (i.e. many terms with the same frequency will always be sorted by "value").

range: A range defines an interval within which all the matching terms' frequencies are summed. This means that if a facet defines a term range for the "creation time" field between the year 2008 to 2010, and another for 2011 to 2012, all matching documents having a creation time within one of these specified ranges will be returned as a sum for that range. Thus you may find 7 documents in the first range, and 18 documents in the second range. Ranges cannot be used with multi-value fields.

For End Users and Portal Administrators

Faceted search is a new feature in Liferay 6.1 (although some of the APIs were first introduced in Liferay 6.0 EE sp2). As such there is little relevance with previous versions other than in direct comparison with the old implementation of the Search Portlet which had no facet capabilities of any kind.

Although the new Faceted Search APIs are used transparently throughout the portal, primary exposure is surfaced through the new Search Portlet implementation.

What follows is a list of features provided by Faceted Search via the Search Portlet.

  1. Aggregation of assets into a single result set: Results from all portlets are returned as a single set and the relevance is normalized among the entire set, regardless of type (i.e. the best results among all types will be at the top). Searching has a more linear cost due to the fact that only a single query is performed. Searching is therefore faster, more intuitive, and more relevant.

    In previous versions of the portal, each Portlet implemented it's own search and returned a separate result set which resulted in several issues:
    • Each portlet invoked it's own query, and each portlet was called in turn resulting in a single portal request generating potentially N queries to the index each with it's own processing time. This lead to increased time to produce the final view.
    • Depending on the order of how portlet searches were called, the results near the bottom may be the most relevant and due to positioning could appear to have less value than those of portlets positioned physically higher up on the page. i.e. the relevance of results was not normalized across all the total results of all portlets.
  2. Default facets: Asset Type, Asset Tags, Asset Categories, and Modified Time range facets are provided by default. These defaults make finding content on the most common facets simple and powerful. Facets details are displayed in the left column of the search portlet and provide information in context of the current search.
    • Asset Type: Performing a search for the term "htc" may return Asset Type facet details which appear as follows:



      The value in parenthesis is the frequency with the term appearing on the left.

      You may notice that as you perform different searches, the Asset Type terms may disappear and re-appear. When a term does not appear it means; a) it was not be found among the results, b) it did not meet the frequency threshold property, or c) it was beyond the maxTerms property (these properties will be discussed more later).
    • Asset Tags: If tags have been applied to any document which appear in the result set, they may appear in the Asset Tag facet:



      Note: Not all tags may appear. In the example above, there are many more than the 10 tags that are listed, but the default configuration for this facet is to show the top 10 most frequently occuring terms as set by it's maxTerms property.
    • Asset Categories: If categories have been applied to any document which appear in the result set, they may appear in the Asset Categories facet:



      Note: Not all categories may appear. In the example above, there are many more than the 10 categories that are listed, but the default configuration for this facet is to show the top 10 most frequently occuring terms as set by it's maxTerms property.
    • Modified Time: All documents appearing in the result set should have an indexed field called "modified" which indicates when the document was created (or updated). The Modified Time facet is a range facet which provides several pre-configured ranges as well as an option for the user to specify a range. All results in the subsequent query should then fall within this range.
  3. Drill down: The next feature allows refining results by selecting terms from each facet thereby adding more criteria to the search to narrow results (referred to as "drilling down" into the results).

    Clicking on terms adds them to the search criteria (currently only one term per facet). They are then listed in what is known as "token style" just below the search input box for convenience and clarity. Clicking the any token's X removes it from the currently selected criteria.

    e.g. Selected the tag "liferay":


    e.g. Additionally, selected the type "Web Content":
  4. Advanced operations: These are supported directly in the search input box. Most of the advanced operations supported by Lucene are supported with only slight variations.

    For a full description of the Lucene syntax see: http://lucene.apache.org/core/old_versioned_docs/versions/3_0_3/queryparsersyntax.html

    Note: Many of the descriptions bellow are copied (almost word for word) from the above reference to account for the similarities but also to highlight the slight variations found between the two.
    • Searching in specific fields: By default, searches are performed against a long list of fields (this is different from Lucene which searches a single specific field by default). Sometimes you want results for a term within a particular field. This can be achieved using the field search syntax:

      <field>:<term> title:liferay

      Searching for a phrase within a field requires surrounding the term with double quotation marks:

      content:"Create categories"

      Note:The field is only valid for the term that it directly precedes, so the query

      content:Create categories will search for the term "Create" in the content field, and the term "categories" will be searched in "all" the default fields.
    • Wildcard Searches: The Search Portlet supports single and multiple character wildcard searches within single terms not within phrase queries.

      To perform a single character wildcard search use the "?" symbol.

      To perform a multiple character wildcard search use the "*" symbol.

      The single character wildcard search looks for terms that match that with the single character replaced. For example, to search for "text" or "test" you can use the search:

      te?t Multiple character wildcard searches looks for 0 or more characters. For example, to search for test, tests or tester, you can use the search:

      test* You can also use the wildcard searches in the middle of a term.

      te*t Note: You cannot use a "*" or "?" symbol as the first character of a search.
    • Fuzzy Searches : Search supports fuzzy searches based on the Levenshtein Distance, or Edit Distance algorithm. To do a fuzzy search use the tilde, "~", symbol at the end of a single word term.

      For example to search for a term similar in spelling to "roam" use the fuzzy search:

      roam~ This search will find terms like foam and roams.

      An additional (optional) parameter can specify the required similarity. The value is between 0 and 1, with a value closer to 1 only terms with a higher similarity will be matched. For example:

      roam~0.8 The default that is used if the parameter is not given is 0.5.
    • Range Searches: Ranges allow one to match documents whose field(s) values are between the lower and upper bound specified by the range. Ranges can be inclusive or exclusive of the upper and lower bounds. Sorting is done lexicographically.

      modified:[20020101000000 TO 20030101000000] This will find documents whose modified fields have values between 2002/01/01 and 2003/01/01, inclusive.

      Note: Liferay's date fields are always formatted according to the value of the property index.date.format.pattern. The format used should be a sortable pattern. The default date format pattern used is yyyyMMddHHmmss. So, when comparing or searching by dates, this format must be used.

      You can also use ranges with non-date fields:

      title:{Aida TO Carmen} This will find all documents whose titles are between Aida and Carmen, but not including Aida and Carmen.

      Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by curly brackets.

      Note: Ranges can only be applied to single value fields.
    • Boolean Operators: Boolean operators allow terms to be combined through logical operations. The Search Portlet supports AND, "+", OR, NOT and "-" as Boolean operators.

      Note: Boolean operators must be ALL CAPS.
      • The OR operator is the default conjunction operator. This means that if there is no Boolean operator between two terms, the OR operator is used. The OR operator links two terms and finds a matching document if either of the terms exist in a document. This is equivalent to a union using sets. The symbol || can be used in place of the word OR.

        To search for documents that contain either "liferay portal" or just "liferay" use the query:

        "liferay portal" liferay or

        "liferay portal" OR liferay
      • The AND operator matches documents where both terms exist anywhere in the text of a single document. This is equivalent to an intersection using sets. The symbol && can be used in place of the word AND.

        To search for documents that contain "liferay portal" and "Apache Lucene" use the query:

        "liferay portal" AND "Apache Lucene"
      • The "+" or required operator requires that the term after the "+" symbol exist somewhere in a field of a single document.

        To search for documents that must contain "liferay" and may contain "lucene" use the query:

        +liferay lucene
      • The NOT operator excludes documents that contain the term after NOT. This is equivalent to a difference using sets. The symbol ! can be used in place of the word NOT.

        To search for documents that contain "liferay portal" but not "Apache Lucene" use the query:

        "liferay portal" NOT "Apache Lucene" Note: The NOT operator cannot be used with just one term. For example,the following search will return no results:

        NOT "liferay portal"
      • The "-" or prohibit operator excludes documents that contain the term after the "-" symbol.

        To search for documents that contain "liferay portal" but not "Apache Lucene" use the query:

        "liferay portal" -"Apache Lucene"
    • Grouping: Search supports using parentheses to group clauses to form sub queries. This can be very useful if you want to control the boolean logic for a query.

      To search for either "liferay" or "apache" and "website" use the query:

      (liferay OR apache) AND website This eliminates any confusion and makes sure that website must exist and either term liferay or apache may exist.
    • Field Grouping: Search supports using parentheses to group multiple clauses to a single field.

      To search for a title that contains both the word "return" and the phrase "pink panther" use the query:

      title:(+return +"pink panther")
    • Proximity Searches and Term Boosting are not supported.

Portlet Configuration

[Updated: Oct 16 2012] Search portlet configurations are currently scoped to the site page, which means that all Search Portlets used in the same site will have the same settings, regardless of their location or position on different pages will have their own configurations; this also includes any instances of the portlet embedded in themes, or other templates.

Display Settings:

  • Basic : This represents the most basic way of controlling the visible facets.

    Display Asset Type Facet: Display or not.
    Display Asset Tags Facet: Display or not.
    Display Asset Categories Facet: Display or not.
    Display Modified Range Facet: Display or not.
  • Advanced: This mode gives ultimate control over the display of facets and is where the true power lies in the Search Portlet. However, it is not for the faint of heart and requires creating a configuration in JSON format. (Future versions of Liferay will include a user friendly user interface for configuration of facets.)

    In it's default configuration, the Search Portlet configuration would equate to the following JSON text:
    {"facets": [
    	{
    		"className": "com.liferay.portal.kernel.search.facet.AssetEntriesFacet",
    		"data": {
    			"frequencyThreshold": 1,
    			"values": [
    				"com.liferay.portlet.bookmarks.model.BookmarksEntry",
    				"com.liferay.portlet.blogs.model.BlogsEntry",
    				"com.liferay.portlet.calendar.model.CalEvent",
    				"com.liferay.portlet.documentlibrary.model.DLFileEntry",
    				"com.liferay.portlet.journal.model.JournalArticle",
    				"com.liferay.portlet.messageboards.model.MBMessage",
    				"com.liferay.portlet.wiki.model.WikiPage",
    				"com.liferay.portal.model.User"
    			]
    		},
    		"displayStyle": "asset_entries",
    		"fieldName": "entryClassName",
    		"label": "asset-type",
    		"order": "OrderHitsDesc",
    		"static": false,
    		"weight": 1.5
    	},
    	{
    		"className": "com.liferay.portal.kernel.search.facet.MultiValueFacet",
    		"data": {
    			"maxTerms": 10,
    			"displayStyle": "list",
    			"frequencyThreshold": 1,
    			"showAssetCount": true
    		},
    		"displayStyle": "asset_tags",
    		"fieldName": "assetTagNames",
    		"label": "tag",
    		"order": "OrderHitsDesc",
    		"static": false,
    		"weight": 1.4
    	},
    	{
    		"className": "com.liferay.portal.kernel.search.facet.MultiValueFacet",
    		"data": {
    			"maxTerms": 10,
    			"displayStyle": "list",
    			"frequencyThreshold": 1,
    			"showAssetCount": true
    		},
    		"displayStyle": "asset_tags",
    		"fieldName": "assetCategoryTitles",
    		"label": "category",
    		"order": "OrderHitsDesc",
    		"static": false,
    		"weight": 1.3
    	},
    	{
    		"className": "com.liferay.portal.kernel.search.facet.ModifiedFacet",
    		"data": {
    			"ranges": [
    				{
    					"range": "[past-hour TO *]",
    					"label": "past-hour"
    				},
    				{
    					"range": "[past-24-hours TO *]",
    					"label": "past-24-hours"
    				},
    				{
    					"range": "[past-week TO *]",
    					"label": "past-week"
    				},
    				{
    					"range": "[past-month TO *]",
    					"label": "past-month"
    				},
    				{
    					"range": "[past-year TO *]",
    					"label": "past-year"
    				}
    			],
    			"frequencyThreshold": 0
    		},
    		"displayStyle": "modified",
    		"fieldName": "modified", 
    		"label": "modified",
    		"order": "OrderHitsDesc",
    		"static": false,
    		"weight": 1.1
    	}
    ]}
    
    The base definition consists of a JSON object with a field of type array named "facets":
    {"facets": []}
    This array must contain elements (which in JSON are called Objects) having the following mandatory structure:
    {
    	"className": ...,
    	"data": ...,
    	"displayStyle": ...,
    	"fieldName": ...,
    	"label": ...,
    	"order": ...,
    	"static": ...,
    	"weight": ...
    }
    
    • "className": This field must contain a string value which is the FQCN (fully qualified class name) of a java implementation class implementing the Facet interface. Liferay provides the following implementations by default:
      "com.liferay.portal.kernel.search.facet.AssetEntriesFacet"
      "com.liferay.portal.kernel.search.facet.ModifiedFacet"
      "com.liferay.portal.kernel.search.facet.MultiValueFacet"
      "com.liferay.portal.kernel.search.facet.RangeFacet"
      "com.liferay.portal.kernel.search.facet.ScopeFacet"
      "com.liferay.portal.kernel.search.facet.SimpleFacet"
      
    • "data": This field takes an arbitrary JSON "Object" (a.k.a. {}) for use by a specific facet implementation. As such, there is no fixed definition of the data field. Each implementation is free to structure it as needed.
    • "displayStyle": This field takes a value of type string and represents a particular template implementation which is used to render the facet. These templates are normally JSP pages (but can also be implemented as Velocity or Freemarker templates provided by a theme if the portal property theme.jsp.override.enabled is set to true). The method of matching the string to a JSP is simply done by prefixing the string with /html/portlet/search/facets/ and appending the .jsp extension.

      e.g. "displayStyle": "asset_tags"

      maps to the JSP

      /html/portlet/search/facets/asset_tags.jsp Armed with this knowledge a crafty developer could create custom display styles by deploying custom (new or overriding) JSPs using a JSP hook.
    • "fieldName": This field takes a string value and indicates the indexed field on which the facet will operate.

      e.g. "fieldName": "entryClassName"

      indicates that the specified facet implementation will operate on the entryClassName indexed field.

      Note: You can identify available indexed fields by checkmarking the Search Portlet's Display Results in Document Form configuration setting and then expanding individual results by clicking the [+] to the left of their title.
    • "label": This field takes a string value and represents the language key that will be used for localizing the title of the facet when rendered.
    • "order": This field takes a string value. There are two possible values:

      "OrderValueAsc" This tells the facet to sort it's results by the term values, in ascending order.

      "OrderHitsDesc" This tells the facet to sort it's results by the term frequency, in descending order.
    • "static": This field takes a boolean value (true or false). A value of true means that the facet should not actually be rendered in the UI. It also means that, rather than using inputs dynamically applied by the end user, it should use pre-set values (stored in it's "data" field). This allows for the creation of pre-configured result domain. The default value is false.

      Image Search Example: Imagine you would like to create a pre-configured search that returns only images (i.e. the indexed field "entryClassName" would be com.liferay.portlet.documentlibrary.model.DLFileEntry and the indexed field "extension" should contain one of bmp, gif, jpeg, jpg, odg, png, or svg). We would need two static facets, one with "fieldName": "entryClassName" and another with "fieldName": "extension". This could be represented using the following facet configuration:
      {
      	"displayStyle": "asset_entries",
      	"static": true,
      	"weight": 1.5,
      	"order": "OrderHitsDesc",
      	"data": {
      		"values": [
      			"com.liferay.portlet.documentlibrary.model.DLFileEntry"
      		],
      		"frequencyThreshold": 0
      	},
      	"className": "com.liferay.portal.kernel.search.facet.AssetEntriesFacet",
      	"label": "asset-type",
      	"fieldName": "entryClassName"
      },
      {
      	"displayStyle": "asset_entries",
      	"static": true,
      	"weight": 1.5,
         	"order": "OrderHitsDesc",
      	"data": {
      		"values": [
      			"bmp", "gif", "jpeg", "jpg", "odg", "png", "svg"
      		],
      		"frequencyThreshold": 0
         	},
      	"className": "com.liferay.portal.kernel.search.facet.MultiValueFacet",
      	"label": "images",
      	"fieldName": "extension"
      }
      
      			
    • "weight": This field takes a floating point (or double) value and is used to determine the ordering of the facets in the facet column of the search portlet. Facets are positioned with the largest values at the top (yes it's counter intuitive and perhaps should be reversed in future versions).

Other Settings

  • Display Results in Document Form: This configuration, if checked, will display each result with an expendable section you can reach by clicking the [+] to the left of the result's title. In Document Form, all of the result's indexed fields will be shown in the expandable section. This is for use in testing search behavior.

    Note: Even if enabled, for security reasons this ability is only available to the portal Administrator role because the raw contents of the index may expose protected information.
  • View in Context: This configuration, if checked, will produce results which have links that target the first identifiable application to which the result is native.

    For example, a Blog entry title will link (or attempt to link) to a Blogs Admin, Blogs, or Blogs Aggregator portlet somewhere in the current site. The exact method of location is defined by the result type's AssetRenderer implementation.
  • Display Main Query: This configuration, if checked, will output the complete query that was used to perform the search. This will appear directly bellow the result area, like this:

  • Display Open Search Results: In previous versions of the portal, the Search Portlet was implemented as a collection of com.liferay.portal.kernel.search.OpenSearch implementation classes which were executed in series. Due to the subsequent re-design of the Search Portlet, the portal itself no longer relies on these implementations for it's primary search. However, third party plugin developers may yet have Open Search implementations which they would like to continue to use. This configuration, if checked, will enable the execution of these third party Open Search implementations and results will appear bellow the primary portal search.

    Note: It is highly recommended that third parties re-design their search code to implement com.liferay.portal.kernel.search.Indexer or more simply to extend com.liferay.portal.kernel.search.BaseIndexer. Thus it will be possible to aggregate custom assets with native portal assets.

For Developers

Key Classes

When implementing a customized search, many of following API classes are important:

com.liferay.portal.kernel.search.SearchContext
com.liferay.portal.kernel.search.SearchContextFactory
com.liferay.portal.kernel.search.facet.config.FacetConfiguration
com.liferay.portal.kernel.search.facet.config.FacetConfigurationUtil
com.liferay.portal.kernel.search.facet.util.FacetFactoryUtil
com.liferay.portal.kernel.search.facet.Facet
com.liferay.portal.kernel.search.Indexer
com.liferay.portal.kernel.search.IndexerRegistryUtil
com.liferay.portal.kernel.search.BaseIndexer
com.liferay.portal.kernel.search.FacetedSearcher
com.liferay.portal.kernel.search.SearchEngineUtil
com.liferay.portal.kernel.search.Hits
com.liferay.portal.kernel.search.Document
com.liferay.portal.kernel.search.facet.collector.FacetCollector
com.liferay.portal.kernel.search.facet.collector.TermCollector

We'll briefly go through the general organization of the above to understand where each class fits into the greater scheme.

SearchContext

The first thing required is to setup a context within which to perform a search. The context defines things like company instance to search, the current user invoking the search, etc. This task is handled by the com.liferay.portal.kernel.search.SearchContext class. Since this class has a wide variety of context properties to deal with, the most effective way to get one is to call the getInstance(HttpServletRequest request) method of the com.liferay.portal.kernel.search.SearchContextFactory class.

SearchContext searchContext = SearchContextFactory.getInstance(request);

Context Properties

Once you have a SearchContext instance, we then can populate values like the pagination style, start and end:

searchContext.setAttribute("paginationType", "more");
searchContext.setEnd(mainSearchSearchContainer.getEnd());
searchContext.setStart(mainSearchSearchContainer.getStart());

There are number of other SearchContext properties that can be set. See the javadocs for a complete list.

Setting up Facets

After we have setup all the appropriate SearchContext properties, we are ready to add the Facets for which we want to collect information. We can add Facets either programatically or through configuration. Programatically adding facets allows the developer to tightly control how the search is used. The following example shows how to add two facets using some provided Facet classes:

Facet assetEntriesFacet = new AssetEntriesFacet(searchContext);
assetEntriesFacet.setStatic(true);
searchContext.addFacet(assetEntriesFacet);

Facet scopeFacet = new ScopeFacet(searchContext);
scopeFacet.setStatic(true);
searchContext.addFacet(scopeFacet);

Note: The above two Facet implementations are not re-usable in that they always operate on specific indexed fields; entryClassName, and groupId (and scopeGroupId) respectively. Other implementations can be re-used with any index fields as demonstrated previously in the Image Search Example.

As shown previously, facets can also be setup using a JSON definition. Using a JSON definition allows for the highest level of flexibility since the configuration can be changed at run-time. These definitions are parsed by the static method load(String configuration) on the com.liferay.portal.kernel.search.facet.config.FacetConfigurationUtil class. This method reads the JSON text and returns a list of com.liferay.portal.kernel.search.facet.config.FacetConfiguration instances.

List<FacetConfiguration> facetConfigurations = FacetConfigurationUtil.load(searchConfiguration);

for (FacetConfiguration facetConfiguration : facetConfigurations) {
	Facet facet = FacetFactoryUtil.create(searchContext, facetConfiguration);

	searchContext.addFacet(facet);
}

Facets as Filters

It should be noted that Facets are always created with reference to the SearchContext. Since facets also behave as the dynamic filter mechanism for narrowing search results, having the SearchContext allows a Facet implementation to observe and react to context changes such as looking for specific parameters which affect it's behavior.

Indexer Implementations

The next step involves obtaining a reference to an indexer implementation. The implementation obtained determines the type of results return from the search.

With respect to searching, there are two categories of Indexer implementations: Asset Specific Searchers and Aggregate Searchers.

Asset Specific Searchers

As the name implies, Asset Specific Searchers always deal with only one specific type of asset. These are the implementations that are provided by developers when creating/designing custom Asset types. Liferay provides the following Asset Specific Searchers:

com.liferay.portal.plugin.PluginPackageIndexer
com.liferay.portlet.blogs.util.BlogsIndexer
com.liferay.portlet.bookmarks.util.BookmarksIndexer
com.liferay.portlet.calendar.util.CalIndexer
com.liferay.portlet.documentlibrary.util.DLIndexer
com.liferay.portlet.journal.util.JournalIndexer
com.liferay.portlet.messageboards.util.MBIndexer
com.liferay.portlet.softwarecatalog.util.SCIndexer
com.liferay.portlet.usersadmin.util.OrganizationIndexer
com.liferay.portlet.usersadmin.util.UserIndexer
com.liferay.portlet.wiki.util.WikiIndexer

A developer tells the portal about Indexer implementations by declaring them in their liferay-portlet.xml file.

<indexer-class>com.liferay.portlet.calendar.util.CalIndexer</indexer-class>

Any number of such implementations may be provided.

Aggregate Searchers

Obtaining a reference to an Asset Specific Indexer requires calling either the getIndexer(Class<?> clazz) or getIndexer(String className) methods on the com.liferay.portal.kernel.search.IndexerRegistryUtil class.

Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);

Aggregate Searchers can return any of the asset types in the index according to the SearchContext and/or facet configuration. Liferay only provides a single aggregate searcher implementation:

com.liferay.portal.kernel.search.FacetedSearcher

Obtaining a reference to this searcher simply involves calling the static getInstance() method of the same class.

Indexer indexer = FacetedSearcher.getInstance();

Note<: When implementing Indexers it is highly recommended to extend the com.liferay.portal.kernel.search.BaseIndexer class.

SearchEngineUtil

Internally each Indexer will make calls to the SearchEngineUtil which handles all the intricacies of the engine implementation. For the purpose of this document, we won't delve into the internals of SearchEngineUtil. But suffice it to say that all traffic to and from the search engine implementation passes through this class, and so when debuging problems it is often beneficial to enable debugging level logging on this class.

Performing the Search

Once an Indexer instance has been obtained, searches are performed by calling its search(SearchContext searchContext) method.

Hits & Documents

The result of the search method is an instance of the com.liferay.portal.kernel.search.Hits class.

Hits hits = indexer.search(searchContext);

This object contains any search results in the form of an array (or list) of com.liferay.portal.kernel.search.Document instances.

Document[] docs = hits.getDocs();

OR

List<Document> docs = hits.toList();

The results display typically involves iterating over this array. Each Document is effectively a hash map of the indexed fields and values.

Facet Rendering

Facet rendering is done by getting Facets from the SearchContext after the search has completed and passing each to a template as defined by the FacetConfiguration:

Map<String, Facet> facets = searchContext.getFacets();
List<Facet> facetsList = ListUtil.fromCollection(facets.values());
facetsList = ListUtil.sort(
	facetsList, new PropertyComparator("facetConfiguration.weight", false, false));

for (Facet facet : facetsList) {
	if (facet.isStatic()) {
		continue;
	}

	FacetConfiguration facetConfiguration = facet.getFacetConfiguration();
	request.setAttribute("search.jsp-facet", facet);

%>

	<liferay-util:include page='<%= "/html/portlet/search/facets/" + facetConfiguration.getDisplayStyle() + ".jsp" %>' />

<%
}

Facet Details (Terms and Frequencies)

A Facet's details are obtained by calling it's getFacetCollector() method which returns an instance of com.liferay.portal.kernel.search.facet.collector.FacetCollector class.

FacetCollector facetCollector = facet.getFacetCollector();

The primary responsibility of this class is to in turn provide access to TermCollector instances primarily by calling the getTermCollectors() method, but also by getting a TermCollector by term value using the getTermCollector(String term) method. There will be a TermCollector for each term that matches the search criteria, as well as the facet configuration.

List<TermCollector> termCollectors = facetCollector.getTermCollectors();

OR

TermCollectorterm termCollector = facetCollector.getTermCollector(term);

And finally, the com.liferay.portal.kernel.search.facet.collector.TermCollector class provides the getFrequency() method.

<%= termCollector.getTerm() %> <span class="frequency">(<%= termCollector.getFrequency() %>)</span>

Rendered facet views (i.e. non-static facets) should result in UI code which allows dynamically passing facet parameters the interpretation by the implementation (see Facets as Filters). There are a number of examples in the /html/portlet/search/facets folder of the Search Portlet.

============================================================

Well, I hope that was useful information.

At the core of all content management lies search and so I'm really excited about the potential of this new search API. As we work on 6.2 and introduce even more innovative new search features, I hope to see Liferay become the most feature rich and extensible search integration platform available in the market. 

Antworten im Thread Autor Datum
This is awesome Ray!!! Thanks for the post... Kamesh Sampath 9. März 2012 20:22
We have abstracted our own Facet framework so... Ray Augé 9. März 2012 20:35
Nice Blog Ray !!! Faceted Search is cool !! And... Tejas Kanani 12. März 2012 02:15
Nice post! Jonas Yuan 13. März 2012 09:15
Your posts are always interesting and... Manish Kumar Gupta 14. März 2012 08:11
That is a lot of information. I think I'm going... Dana Oredson 14. März 2012 19:19
Really great detailing about faceted search... Nagendra Kumar Busam 14. März 2012 22:47
Thanks All. Ray Augé 15. März 2012 07:24
Ray I always have an eagerness for reading your... Erin Caroll 19. März 2012 21:04
Hi..i m new to liferay..i want to create search... Siva Ranjani 21. März 2012 23:14
Hi Ray, I wanna thank you about this post... Firas BD 22. März 2012 01:42
@Siva, the best sample code is the search... Ray Augé 22. März 2012 06:16
@Ray Augé: the error is with the default search... Firas BD 22. März 2012 06:35
Can you file a ticket for this which outlines... Ray Augé 22. März 2012 06:39
@ Ray: http://issues.liferay.com/browse/LPS-26227 Firas BD 22. März 2012 06:53
Hi Ray, I'm new to Liferay and need your... Vlad Kuzmyk 26. März 2012 09:16
Hi, Any progress on this. I have modified... Suyash Bhalekar 3. Juni 2013 00:22
Hi, Any progress on this. I have modified... Suyash Bhalekar 3. Juni 2013 00:22
Nice post, and timely too. I was just about to... Joseph Toman 24. März 2012 12:45
Never mind about that second question, found it... Joseph Toman 24. März 2012 15:50
Hi Ray, Thanks for the article. I'm trying to... Jonathan Lloyd 9. April 2012 09:09
Try +(+assetCategoryIds:11703... Ray Augé 9. April 2012 09:20
AND should be used more specifically like so: ... Ray Augé 9. April 2012 09:20
Hi Ray, Thanks for the quick reply! I have... Jonathan Lloyd 9. April 2012 09:34
Ray, just found this post after looking into... Dave Weitzel 27. April 2012 13:41
Hi Ray, I have a problem with create... Salvador Baena 10. Mai 2012 03:25
It is possible that Liferay can index content... Amit Doshi 22. Mai 2012 00:53
@Salvador, make your "noticia" facet static... Ray Augé 22. Mai 2012 07:07
Wow, incredible article! I would like to know... Florencia Gadea 23. Mai 2012 07:53
It's true that the search portlet doesn't start... Ray Augé 23. Mai 2012 08:21
Thanks Ray for the prompt reply. I just added a... Florencia Gadea 23. Mai 2012 08:43
Thank you very much Ray. Solved. Facet to... Salvador Baena 23. Mai 2012 10:00
Hi, I would like to know how drill down can be... ASI Register 25. Mai 2012 02:42
Yeah, this was deferred to a later version.... Ray Augé 25. Mai 2012 12:35
Hi Ray, I would like to know what is the best... Matteo S 28. Juni 2012 08:44
Facets are for single fields only (both Bobo... Ray Augé 28. Juni 2012 08:57
BTW, the "Multi" in the name MultiValueFacet is... Ray Augé 28. Juni 2012 09:08
Hi Ray, I have the requirements to pass... Himanshu Modi 29. Juni 2012 03:27
Typo--(assetCategoryNames:topic2... Himanshu Modi 29. Juni 2012 04:24
The correct way to do that would be by passing... Ray Augé 20. Juli 2012 06:16
Hi Ray, is there any way to integrate a custom... Kim Anna Kunc 16. August 2012 01:16
I figured it it out, my Indexer extends... Kim Anna Kunc 16. August 2012 01:45
Ok, great! I'm glad you managed to figure it... Ray Augé 16. August 2012 07:40
Ray, thanks for your reply! What would think of... Kim Anna Kunc 28. August 2012 00:57
That would be cool (JIRA feature request?). Ray Augé 29. August 2012 09:41
Hi Ray, A really useful article. Can you tell... Denis Signoretto 11. September 2012 04:30
Unfortunately not at the moment (JIRA feature... Ray Augé 11. September 2012 06:25
Hi Ray, I do understand your point about... Matteo S 12. September 2012 08:50
Thanks for this detailed blog about Faceted... Gwowen Fu 6. Oktober 2012 09:33
The data is not cached so much as it may be... Ray Augé 16. Oktober 2012 13:52
@Matteo, As I stated previously, you can use... Ray Augé 16. Oktober 2012 14:01
Hi Ray, Thank you for very informative and... Yogesh Sharma 24. Oktober 2012 23:20
@Yogesh, that is correct! Thanks for pointing... Ray Augé 29. Oktober 2012 08:39
Hi Ray, Is there a way to exclude certain... Bart Simpson 21. November 2012 04:50
A facet by it's very nature can only search one... Ray Augé 21. November 2012 08:01
Hi Ray, Thank you for very informative blog. ... Jonas Yuan 21. November 2012 09:00
Jonas, categoryId is better in this case. Ray Augé 21. November 2012 09:03
Hi Ray, I'm new to Liferay in my custom theme... Matteo Galletti 14. Dezember 2012 09:30
Ok, I think I see the problem. First, the... Ray Augé 14. Dezember 2012 10:19
Hi Ray, This info. is really good. i have some... Saurabh Gupta 7. Januar 2013 04:11
Ray, Is putting the default search... Mike Ring 29. Januar 2013 12:50
Hi Ray, I've implemented a custom Facet and... Gunther Verhemeldonck 21. Februar 2013 04:49
I the case of Facet class implementations, we... Ray Augé 22. Februar 2013 07:44
We have a problem with the facet search. If... Gunther Verhemeldonck 26. Februar 2013 05:13
Sorry to hear that. Can you enable showing the... Ray Augé 26. Februar 2013 06:36
We believe it might be a bug. The... Gunther Verhemeldonck 27. Februar 2013 01:06
Confirmed as a bug. Gunther Verhemeldonck 21. März 2013 08:32
Hello Ray, Nice explanation. In... Yagneswar Macherla 1. März 2013 08:01
Hi, it seems that with 6.1.1 CE boolean... Test Test 8. April 2013 04:17
I have a problem with the fuzzy search. I have... haikel thamri 26. April 2013 07:24
AssetTags are not indexed! your entryClassName... Ray Augé 26. April 2013 07:27
I have implemented a custom indexer in my... haikel thamri 26. April 2013 07:33
Ok, can you give me some examples of indexed... Ray Augé 26. April 2013 07:35
With luke this query for example... haikel thamri 26. April 2013 07:42
excuse me the query is +(name:routar~)... haikel thamri 26. April 2013 07:42
excuse me the query is +(name:routar~)... haikel thamri 26. April 2013 07:42
Ok, as soon as I get a chance will play with... Ray Augé 26. April 2013 07:45
Done! LPS-34774 Thank you :) haikel thamri 26. April 2013 08:13
Hi Ray, Great post!! I'm having a few issues... Brian Scott Schupbach 2. Mai 2013 14:23
for anyone interested...This has been confirmed... Brian Scott Schupbach 12. Juni 2013 11:29
by "this" I mean "I can't seem to filter by... Brian Scott Schupbach 12. Juni 2013 11:30
Hi Ray, I have implemented a custom indexer in... haikel thamri 26. April 2013 07:37
Sure, I got that part. Can you give me some... Ray Augé 26. April 2013 07:40
I am using sorting by a field in Webcontent... Sultan Zahir Khan 12. Juni 2013 10:17
Hello Ray, Thanks for the great post. I' m... Huage Chen 14. Juni 2013 08:28
Is it possible to configure the faceted Search... Bert Godon 4. September 2013 04:21
yes it can be done by selecting only these... Himanshu Modi 4. September 2013 10:35
Please see... Ray Augé 4. September 2013 11:29
H Ray, I tried to add ... Nabil Bahtat 24. Oktober 2013 13:22
It must be an entity which is indexed. Ray Augé 24. Oktober 2013 13:24
Hi Ray, How to make Polls portlet an indexed... Nabil Bahtat 28. Oktober 2013 23:21
Minimally, you need to create and register an... Ray Augé 29. Oktober 2013 09:23
Hi Ray, I managed to do all the tasks about... Nabil Bahtat 12. Januar 2014 11:24
I have a question about how the search is... Robert Zahm 2. Dezember 2013 15:14
Is it possible to highlight the searchresult... lili samanta 13. März 2014 07:00
Hi Ray , we are passing facets as json . but... deepthi p 26. März 2014 03:14
Hi Ray, Could you please expand on the... Adam Steiner 15. April 2014 14:36
Hi Ray, We have requirement for search only... Nitin Yeola 19. Mai 2014 03:14
Good Morning. I need to make through faceted... Miguel González 28. Oktober 2014 01:10
Hi Ray, I have installed liferay 6.2 GA2... Alba Garcia 20. März 2015 06:38
Because I believe what you are looking for is ... Ray Augé 21. März 2015 13:10
Thanks Ray! I have imported the... Alba Garcia 29. März 2015 23:32
Hi Ray, In Liferay 7 M7, I found following... Fuad Efendi 24. August 2015 13:15

This is awesome Ray!!! Thanks for the post
Just couple of questions around the frameworks used did we try to use Solor or still continued with Lucene and wrote our facet search framework.
Gepostet am 09.03.12 20:22.
We have abstracted our own Facet framework so that we could build it more or less on any engine. For Lucene, facet support is implemented using the Bobo engine (http://code.google.com/p/bobo-browse/) and in the case of Solr we just use it's features directly. In both cases we wrap the underlying technology with our own API. The idea being that you could plug any engine in back there and our front end APIs don't need to change. The API is very simple for facet support.
Gepostet am 09.03.12 20:35 als Antwort auf Kamesh Sampath.
Nice Blog Ray !!!
Faceted Search is cool !!
And this blog covers lots of details regarding Search.
Thanks for the post.
Gepostet am 12.03.12 02:15.
Your posts are always interesting and informative. Thanks for sharing this with everyone Ray!!!
Gepostet am 14.03.12 08:11.
That is a lot of information. I think I'm going to need to read it several times in order to hold it all in my head. Nice work. It looks like a lot of time and effort went into this post.
Gepostet am 14.03.12 19:19.
Really great detailing about faceted search feature.
Gepostet am 14.03.12 22:47.
Ray I always have an eagerness for reading your posts and articles because I know all your articles are informative as well as knowledgeable..
Gepostet am 19.03.12 21:04.
Hi..i m new to liferay..i want to create search portlet using lucene..can u suggest steps for me..any sample code...

Thank you..
Gepostet am 21.03.12 23:14 als Antwort auf Erin Caroll.
Hi Ray,
I wanna thank you about this post because it's so informative, but I have just a problem: when for example I am searching for a word, and results are in more than one page when I click to go to the next page (I click "More") I got error and no results appear ..
Gepostet am 22.03.12 01:42 als Antwort auf Siva Ranjani.
@Siva, the best sample code is the search portlet itself: https://github.com/liferay/liferay-portal/blob/master/portal-web/docroot/html/po­rtlet/search/main_search.jspf

@Firas, is the error with the default search portlet or with custom code?
Gepostet am 22.03.12 06:16 als Antwort auf Firas BD.
@Ray Augé:
the error is with the default search portlet in Liferay 6.1: and this is the error syntax:

12:06:15,737 ERROR [IncludeTag:154] com.liferay.portal.kernel.search.SearchException: java.lang.IllegalArgumentException: fromIndex(20) > toIndex(5)
at com.liferay.portal.kernel.search.FacetedSearcher.search(FacetedSearcher.java:106­)
at org.apache.jsp.html.portlet.search.search_jsp._jspService(search_jsp.java:1073)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilt­erChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.­java:210)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilterChain.doFilter(In­vokerFilterChain.java:72)
at com.liferay.portal.kernel.servlet.filters.invoker.InvokerFilter.doFilter(Invoker­Filter.java:70)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilt­erChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.­java:210)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java­:684)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.j­ava:593)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.jav­a:530)
at com.liferay.taglib.util.IncludeTag.include(IncludeTag.java:323)
at com.liferay.taglib.util.IncludeTag._doInclude(IncludeTag.java:418)
at com.liferay.taglib.util.IncludeTag.doEndTag(IncludeTag.java:92)
Caused by: java.lang.IllegalArgumentException: fromIndex(20) > toIndex(5)
at java.util.SubList.<init>(AbstractList.java:604)
at java.util.RandomAccessSubList.<init>(AbstractList.java:758)
Gepostet am 22.03.12 06:35 als Antwort auf Ray Augé.
Can you file a ticket for this which outlines the exact steps you used to reproduce it? I'll take a look as soon as I get a chance.
Gepostet am 22.03.12 06:39 als Antwort auf Firas BD.
@ Ray:
http://issues.liferay.com/browse/LPS-26227
Gepostet am 22.03.12 06:53 als Antwort auf Ray Augé.
Nice post, and timely too. I was just about to implement search in a project I'm working on. A couple of questions: you said that proximity search and term boosting aren't supported. Is that just in the search portlet, or in the underlying API as well?
Also, in the development part of the article your code refers to something called mainSearchContainer . What is it, and where'd you get it from? Thanks.
Gepostet am 24.03.12 12:45.
Never mind about that second question, found it in main_search.jspf .
Gepostet am 24.03.12 15:50 als Antwort auf Joseph Toman.
Hi Ray,

I'm new to Liferay and need your advise.

I've created a hook to a search portlet and have a couple of questions:
1. The start page is view.jsp and conains only <liferay-ui:search />. how would I bypass it so it would go directly to main_search.jsp?

2. In my Document library I have categories Monthly Reports and Quarterly Reports. I want to place two links(like facets) with category names and when user clicks it would process the search only for selected category. How would you suggest to approach this task?

Or maybe i need to create a custom search portlet based on a search portlet. Is it a good way to copy all the code from custom portlet into my portlet and modify it?

Thank you in advance
Gepostet am 26.03.12 09:16 als Antwort auf Firas BD.
Hi Ray,

Thanks for the article. I'm trying to get a faceted search to work using an "AND" condition for the assetCategoryIds field, however it never returns any results. I enabled debug output on both the SearchEngineUtils and LuceneIndexSearcherImpl classes and the query string output is "+(+(companyId:10154) +(assetCategoryIdsemoticon11703 AND 11804)) +createDate:[19700101000000 TO 20121231235959] +((+(entryClassName:com.liferay.portlet.journal.model.JournalArticle) +(status:0))))".

To test the lucene syntax, I also used the code below to produce a Query object and it works fine. Do you have any ideas on what might be happening? Thanks in advance for the help.

Query query = StringQueryFactoryUtil.create("+(+(companyId:10154) +(assetCategoryIdsemoticon11703 AND 11804)) +createDate:[19700101000000 TO 20121231235959] +((+(entryClassName:com.liferay.portlet.journal.model.JournalArticle) +(status:0))))");

Hits hits = SearchEngineUtil.search(searchContext.getCompanyId(), query, QueryUtil.ALL_POS, QueryUtil.ALL_POS);
Gepostet am 09.04.12 09:09.
Try

+(+assetCategoryIds:11703 +assetCategoryIds:11804)

it's easier on the parser and means the same thing.
Gepostet am 09.04.12 09:20 als Antwort auf Jonathan Lloyd.
AND should be used more specifically like so:

assetCategoryIds:11703 AND assetCategoryIds:11804
Gepostet am 09.04.12 09:20 als Antwort auf Ray Augé.
Hi Ray,

Thanks for the quick reply! I have used "+" instead of "AND", but still get the same result.

I'm not very familiar with lucene, but it seems like the problem is that based on the way I am setting the attribute values in the SearchContext object and have the facet defined, the objects that build the query string will only output the "assetCategoryIds" text just once. For example, the query string would look like +(assetCategoryIds:+11703 +11804) instead of +(+assetCategoryIds:11703 +assetCategoryIds:11804).

As noted above, I'm using the SearchContext object to set the attributes of the assetCategoryIds field, but I don't see a way to include multiple arguments into that one field with out concatenating them together myself. Something like the code below. I've also tried setting the andSearch property on the SearchContext with no success.

searchContext.setAttribute("assetCategoryIds", convertCategoryIdsToAndString(categoryIds));
Gepostet am 09.04.12 09:34 als Antwort auf Ray Augé.
Ray, just found this post after looking into Search results and facets in more detail for our customization work.

I have one question though? can we get the facet tags and categories localized?(displayed in the facets/asset_tags.jsp as well as under relevant search item).
When you have multi-lingual site it looks odd if the categories are in the base locale for the site. The categories are translated when displayed within the relevant portlet (eg document library).
I understand these are now facets in a search engine result list but the user isnt going to understand that,
Gepostet am 27.04.12 13:41.
Hi Ray,

I have a problem with create pre-configured to search only returns That tag "noticia"
The search returns all the content I type "com.liferay.portlet.journal.model.JournalArticle"

My code is this:

{facets: [
{className: 'com.liferay.portal.kernel.search.facet.AssetEntriesFacet',
data: {frequencyThreshold: 1,
values: [
'com.liferay.portlet.journal.model.JournalArticle'
]},
displayStyle: 'asset_entries',
fieldName: 'entryClassName',
label: 'asset-type',
order: 'OrderHitsDesc',
static: false,
weight: 1.5},
{className: 'com.liferay.portal.kernel.search.facet.MultiValueFacet',
data: {frequencyThreshold: 1,
values: [
'noticia'
]},
displayStyle: 'asset_entries',
fieldName: 'assetTagNames',
label: 'tag',
order: 'OrderHitsDesc',
static: false,
weight: 1.5},
{className: 'com.liferay.portal.kernel.search.facet.MultiValueFacet',
data: {displayStyle: 'list',
frequencyThreshold: 1,
maxTerms: 10,
showAssetCount: true},
displayStyle: 'asset_tags',
fieldName: 'assetTagNames',
label: 'tag',
order: 'OrderHitsDesc',
static: false,
weight: 1.4},
{className: 'com.liferay.portal.kernel.search.facet.MultiValueFacet',
data: {displayStyle: 'list',
frequencyThreshold: 1,
maxTerms: 10,
showAssetCount: true},
displayStyle: 'asset_tags',
fieldName: 'assetCategoryNames',
label: 'category',
order: 'OrderHitsDesc',
static: false,
weight: 1.3},
{className: 'com.liferay.portal.kernel.search.facet.RangeFacet',
data: {frequencyThreshold: 1,
ranges: [{label:'modified',
range:'[19700101000000 TO *]'}]},
displayStyle: 'modified',
fieldName: 'modified',
label: 'modified',
order: 'OrderHitsDesc',
static: false,
weight: 1.1}]}

Thank you very much.
Best regards.
Gepostet am 10.05.12 03:25.
It is possible that Liferay can index content of PDF documents so it can show up in the search ?
Gepostet am 22.05.12 00:53 als Antwort auf Salvador Baena.
@Salvador, make your "noticia" facet static since you are forcing passing a single value.

@Amit, Liferay does it's best attempt to index PDFs automatically (it can't get content from a PDF filled only with scanned images for instance).
Gepostet am 22.05.12 07:07 als Antwort auf Amit Doshi.
Wow, incredible article! I would like to know what is the best way to let the user filter by asset type before hand, before perfoming the search. For example, the user could enter the word "water", and then, from a checkboxes list, choose the asset type to look into, for example, Blog entries. And that would search the word water in blog entries only.
Gepostet am 23.05.12 07:53 als Antwort auf Ray Augé.
It's true that the search portlet doesn't start in the mode having performed a default search (a search with no keywords). If it did, then you would see all the facets available, and then you would see and could select the asset type you want to search within and then add keywords. I think that addresses the scenario you are asking about. Perhaps it would be possible to add that behavior is a configuration option of the portlet. It wouldn't be hard. Can you make a feature request in JIRA (http://issues.liferay.com)?
Gepostet am 23.05.12 08:21 als Antwort auf Florencia Hernández.
Thanks Ray for the prompt reply. I just added a request: http://issues.liferay.com/browse/LPS-27514
Gepostet am 23.05.12 08:43 als Antwort auf Ray Augé.
Thank you very much Ray. Solved.

Facet to filter by tag:

{facets: [
{className: 'com.liferay.portal.kernel.search.facet.AssetEntriesFacet',
data: {frequencyThreshold: 1,
values: [
'com.liferay.portlet.journal.model.JournalArticle'
]},
displayStyle: 'asset_entries',
fieldName: 'entryClassName',
label: 'asset-type',
order: 'OrderHitsDesc',
static: false,
weight: 1.5},
{className: 'com.liferay.portal.kernel.search.facet.MultiValueFacet',
data: {frequencyThreshold: 1,
values: [
'noticia'
]},
displayStyle: 'asset_entries',
fieldName: 'assetTagNames',
label: 'tag',
order: 'OrderHitsDesc',
static: true,
weight: 1.5}]}

Best regards
Gepostet am 23.05.12 10:00 als Antwort auf Florencia Hernández.
Hi,

I would like to know how drill down can be allowed... Even I select a tag in result view, each tag is replaced when I choose another one.

Thanks for your answer emoticon
Gepostet am 25.05.12 02:42.
Yeah, this was deferred to a later version. Technically the backend code can handle any number of arguments per facet, but in order to get a first cut, simple to use UI we opted to limit it to only a single argument per facet. BUT, since it's only a limitation from the UI, you can easily create custom facet view template (jsp hook) that overrides the default and allows multiple selection per facet.

Can you open a feature request so we can track this for future versions?
Gepostet am 25.05.12 12:35 als Antwort auf ASI Register.
Hi Ray,
I would like to know what is the best way to add a custom facet implementation.
I am trying to implement drilled-down search, and I need to produce an AND query for MultiValueFacet.
Looking at source, I believe that this can't be done, because termQuery has booleanClause hardcoded (added request http://issues.liferay.com/browse/LPS-28228).

Thanks in advance
Gepostet am 28.06.12 08:44 als Antwort auf Ray Augé.
Facets are for single fields only (both Bobo [our lucene facet impl] and Solr only have APIs for collecting facet on single fields at a time). But if you need to refine the underlying query so that it reflects some custom logic, then you can do that by passing an array of BooleanClauses to the searchContext before calling search in the FacetedSearcher.

SearchContext searchContext = .. // setup the context
Indexer indexer = FacetedSearcher.getInstance();
searchContext.setBooleanClauses(BooleanClause[] booleanClauses)
Hits hits = indexer.search(searchContext);

Note: An AND is simply a MUST "Occur" clause around a number of other Query instances (or Clauses).
Gepostet am 28.06.12 08:57 als Antwort auf Matteo S.
BTW, the "Multi" in the name MultiValueFacet is not to reflect how it is used with respect to the number of fields to collect data from, but rather to indicate the "type" of field it can be used with. In this case fields with "multiple" values.

In indexing engines, fields generally fall into one of two broad classes:
- single value fields (like a number, fixed string token)
- multi-value fields (like text, or arrays of values)

There are certain types of operations that can take place on each of those two classes of fields. For instance, you can't do a Range query on a multi-value field. you generally can't sort a result set on a multi-value field, single value fields must generally be exact matches (setting aside regex matching obviously), etc.
Gepostet am 28.06.12 09:08 als Antwort auf Ray Augé.
Hi Ray,
I have the requirements to pass multiple categories names while searching. But Faceted searcher is not giving the results for multiple categories.
For example while I pass assetCategoryNames field value as comm separated (say topic2,COUNTRY). The full query that is built in FacetedSearcher.java class looks like ----

"+(+(companyId:10154) +(assetCategoryNames:topic2 COUNTRY) +((+(entryClassName:com.liferay.portlet.bookmarks.model.BookmarksEntry)) (+(entryClassName:com.liferay.portlet.blogs.model.BlogsEntry)) (+(entryClassName:com.liferay.portlet.calendar.model.CalEvent)) (+(entryClassName:com.liferay.portlet.documentlibrary.model.DLFileEntry) +(status:0)) ..........".

Above if you see the part of query---" (assetCategoryNames:topic2 COUNTRY) ", you will notice that category names are coming but there is no boolean operator added by the system. I have gone through all the above threads, I found ur comments but could not get it completely as what needs to be done to select multiple categories at one time while searching.
If any booleanClause need to be set in serachContext then how and what it should be .

Please let me know the solution if you are aware of this scenario.

Thanks in advance,
Himanshu Modi
Gepostet am 29.06.12 03:27 als Antwort auf Ray Augé.
Typo--(assetCategoryNames:topic2 assetCategoryNames:COUNTRY) is the correct query I'm getting.
Gepostet am 29.06.12 04:24 als Antwort auf Himanshu Modi.
The correct way to do that would be by passing a set of additional BooleanClauses to the searchContext.setBooleanClauses(BooleanClause[] clauses) method just before making the search. Facets are not designed for doing filtering only for collecting metrics.
Gepostet am 20.07.12 06:16 als Antwort auf Himanshu Modi.
Hi Ray,
is there any way to integrate a custom portlet into the asset entries facet ?
My portlet has it's custom Indexer that is registered via liferay-portlet.xml and I added my model in the search-portlet's configuration. If I add an OpenSearch implementation the results are displayed at the bottom of the search, but I can't get it to work with the faceted search. What am I missing?
Gepostet am 16.08.12 01:16 als Antwort auf Ray Augé.
I figured it it out, my Indexer extends BaseIndexer but somehow not all keywords are set for the facet query to match my documents. I was missing fields "COMPANY_ID" and "GROUP_ID" that are only set in BaseIndexer if your model is an instance of "AuditedModel" which apparently my model class is not.
Gepostet am 16.08.12 01:45 als Antwort auf Kim A Kunc.
Ok, great! I'm glad you managed to figure it out. Yes, AuditedModel is a helper interface around entities designed to support multi-tenancy.

AuditedModel interface will be automatically added to your Model when the entity definition contains the fields: companyId, createDate, modifiedDate, userId, userName.

Similarly, the GroupedModel interface provides support for scoping models to groups (a.k.a. Sites) and is applied if the entity is an AuditedModel + has the groupId field.

There are several other automatically applied interfaces derived from entity columns, like workflow, attached, resourced, etc.

Apparently this is a subject still in need of documentation.
Gepostet am 16.08.12 07:40 als Antwort auf Kim A Kunc.
Ray, thanks for your reply!
What would think of a new feature in the service builder definition that would automatically create these audit fields i.e. a new property "auditedModel=true/false" ?
Gepostet am 28.08.12 00:57 als Antwort auf Ray Augé.
That would be cool (JIRA feature request?).
Gepostet am 29.08.12 09:41 als Antwort auf Kim A Kunc.
Hi Ray,

A really useful article. Can you tell me if the same functionalities are available through web services or JSON requests (via portal-client.jar) ?

Thanks,
Denis.
Gepostet am 11.09.12 04:30 als Antwort auf Ray Augé.
Unfortunately not at the moment (JIRA feature request?).
Gepostet am 11.09.12 06:25 als Antwort auf Denis Signoretto.
Hi Ray,
I do understand your point about facet's design. However, as others have pointed out, there's a strong use case regarding drilled down search.
As of 6.1GA2, I don't see any possible solution which can be developed by using a jsp hook. We can't use multiple facets on the same term, and current implementation has BooleanClauseOccur.SHOULD hardcoded.
MultiValueFacet (btw thanks for explaining its name) does handle multiple terms, so why you say that ain't the right place to edit the query?

Look at @Himanshu case as example:
- requirement: filter search with multiple terms on the same element
- terms:topic2,COUNTRY
- current implementation produces (assetCategoryNames:topic2 assetCategoryNames:COUNTRY): result is OR between these clauses
- my proposal http://issues.liferay.com/browse/LPS-28228: let admin decide facet clause
example result with (AND -BooleanClauseOccur.MUST ) -> (assetCategoryNames:topic2 AND assetCategoryNames:COUNTRY)

I don't want to use a single facet to search on multiple fields, instead I need the option to produce and AND booleanQuery.
I'm already using this approach on a couple of projects, because of deadlines, but I'm more than open to suggestions on a better way to implement this. Your explanations are really valuable.

Thanks for your response, and sorry for my English..
Matteo
Gepostet am 12.09.12 08:50 als Antwort auf Ray Augé.
Thanks for this detailed blog about Faceted Search API.
I am having an issue. The search is returning articles with old articleID.

I have a portlet to add articles with articleID set to article title, later I change the portlet to delete all articles and add articles with articleID generated by Liferay.

Problem happened, the data returned is the old article created before. The article is still using title as articleID instead of system generated ID.

I tried to clear cache from Server Administration and tried to restart server several times and still the Faceted Search API returns old article. I checked the database and it is not there.

Where is the data cached?
Gepostet am 06.10.12 09:33.
The data is not cached so much as it may be that the indexes are out of sync with the real data (in the Demoticon. Try reindexing the search engines (you can do that all at once via the Admin portlet, or individually by portlet through the plugins configurations portlet).
Gepostet am 16.10.12 13:52 als Antwort auf Gwowen Fu.
@Matteo, As I stated previously, you can use the searchContext.setBooleanClauses(BooleanClause[] clauses) method to add more filtering. Such clauses can implement whatever complex logic you wish to add without causing the facet collector to process for that data (which if all you want to do is filter, is really the wrong mechanism).
Gepostet am 16.10.12 14:01 als Antwort auf Ray Augé.
Hi Ray, Thank you for very informative and helpful blog.

I would like to add something more in detail here:
We sometime keep data in web content structure fields, and custom fields. Following are naming pattern of these fields:

Structure fields can be referred as:
"web_content/structure-field-name"
Here structure-field-name name of field in webcontent structure.

Custom fields can be referred as:
"expando/custom_fields/custom_field_key"
Here custom_field_key is key of custom field for entity.

These can be used in facet configuration with additional display style (via hook).
Gepostet am 24.10.12 23:20 als Antwort auf Ray Augé.
@Yogesh, that is correct! Thanks for pointing that out. We wanted to make sure any field in the index was accessible for facet collection, including custom fields, including document type fields which will be encoded a little differently as "ddm/<ddmStructureId>/<fieldName>". Sadly, it's true that the use of <ddmStructureId> is not ideal and there has already been discussion to perhaps provide an alternative that is more "usable" in future versions.
Gepostet am 29.10.12 08:39 als Antwort auf Yogesh Sharma.
Hi Ray,

Is there a way to exclude certain fields? Here it only gives option to specify fields and values that are to be searched. What about the scenario : search all the facets except for one facet. Or search all except fieldX with valueY? I suppose this is only possible for now with PostProcessorHook?
Gepostet am 21.11.12 04:50 als Antwort auf Ray Augé.
A facet by it's very nature can only search one field.. so I'm not clear on that question.

It's also possible to apply an array of QueryClauses on the SearchContext to filter the reqults. This is how I would implement the: "Or search all except fieldX with valueY?" req. But that would require a hook at the moment.
Gepostet am 21.11.12 08:01 als Antwort auf Bart Simpson.
Hi Ray, Thank you for very informative blog.

Question:
suppose that there are two categories / tags with same name in Global group and current group; how could we distinguish them in facets by names? is it better to use category ID / tag ID?
Gepostet am 21.11.12 09:00 als Antwort auf Ray Augé.
Jonas, categoryId is better in this case.
Gepostet am 21.11.12 09:03 als Antwort auf Jonas Yuan.
Hi Ray, I'm new to Liferay

in my custom theme I put search portlet at runtime with the following code:

$velocityPortletPreferences.setValue("portlet-setup-show-borders","false")
$velocityPortletPreferences.setValue("advancedConfiguration","true")
$velocityPortletPreferences.setValue("searchConfiguration","'facets':[{'displayS­tyle':'asset_entries','weight':1.5,'s[......]")
$theme.runtime("3_INSTANCE_kw01","",$velocityPortletPreferences.toString())
$velocityPortletPreferences.reset()

where in "searchConfiguration", I insert a new line to make sure that the portlet can search a custom entity .

But when in the portal I push the search command, these configurations are not observed.
Gepostet am 14.12.12 09:30 als Antwort auf Ray Augé.
Ok, I think I see the problem. First, the search portlet is not instanceable, which means you can remove the "_INSTANCE_kw01" portion of the portletId. Secondly, because the portlet is not instanceable, you have to use a different technique to set it's preferences. See this gist https://gist.github.com/4287391 (there are actually 2 different preferences, the preferences, and the setup). ;)
Gepostet am 14.12.12 10:19 als Antwort auf Matteo Galletti.
Hi Ray, This info. is really good. i have some requirement but i don't know how to do this. My requirement is "suppose with search portlet there is 3 radio button 1st company tag, 2nd is for message board and 3rd for site. after selecting any radio button where and which value i need set or what code modification i need to do."

Thank you in Advance
Gepostet am 07.01.13 04:11 als Antwort auf Ray Augé.
Ray,
Is putting the default search configuration in a custom theme (in the link you posted the portal_normal.vm file) the preferred way to change the default search configuration for all search portlets? I couldn't get it to work and was wondering if there's a better way. I'm also trying to add a custom entity to the advanced search configuration for all search portlets in my app.
Thanks.
Gepostet am 29.01.13 12:50 als Antwort auf Ray Augé.
Hi Ray,
I've implemented a custom Facet and registered a JSP in the hook for it. After registering the facet in the Search Portlet I receive a ClassNotFoundException.
How would you get a custom Facet class on the portal classpath? Should I repackage it and drop it in the Liferay classpath? The class is now contained within the hook project.
Thanks
Gepostet am 21.02.13 04:49.
I the case of Facet class implementations, we don't currently have a real "hook" mechanism for those, sorry. You'll have to do as you suggested and drop that code into the portal classpath (ROOT/WEB-INF/lib/your.jar or ROOT/WEB-INF/classes/your.class).

(Alternatively you could use an EXT plugin emoticon sorry about that).
Gepostet am 22.02.13 07:44 als Antwort auf Gunther Verhemeldonck.
We have a problem with the facet search. If we perform a search and drill-down on a Category, it seems the search doesn't take into account the search string. Instead of receiving less hits, we receive MORE hits that are not related to the search term we entered.

If we trace, the query does seem to take into account both the search query as well as the Category we clicked to drill-down.
In the traces we also noticed that the BaseIndexer prints out the Search engine ID for each facet, but in our case this ID is always empty.

Does anybody have an idea what can be the root cause, knowing that search is out-of-the-box and we have all known EE fixes installed.

Thanks in advance.
Gepostet am 26.02.13 05:13 als Antwort auf Ray Augé.
Sorry to hear that. Can you enable showing the query (in the portlet configuration) and then list the query without and then with the category selection?
Gepostet am 26.02.13 06:36 als Antwort auf Gunther Verhemeldonck.
We believe it might be a bug. The categoryTitle is added to the Lucene Query in the search term related part of the query, so as a result the it finds all items related to the category not taking into account the entered search term (since it is OR).

Query 1:
+(+(companyId:10154) +
(
(+(entryClassName:com.liferay.portlet.bookmarks.model.BookmarksEntry))
(+(entryClassName:com.liferay.portlet.blogs.model.BlogsEntry))
(+(entryClas­sName:com.liferay.portlet.documentlibrary.model.DLFileEntry) +(status:0))
(+(entryClassName:com.liferay.portlet.journal.model.JournalArticl­e) +(status:0))
) +
(+(groupId:10405) +(scopeGroupId:10405))
) +
(assetCategoryTitles:*test* assetCategoryTitles_nl_BE:*test* assetTagNames:*test* ....


Query 2 (drill-down on 'Enterprise'-category):

+(+(companyId:10154) +(assetCategoryTitles:Enterprise) +
(
(+(entryClassName:com.liferay.portlet.bookmarks.model.BookmarksEntry))
­ (+(entryClassName:com.liferay.portlet.blogs.model.BlogsEntry))
(+(entryClassN­ame:com.liferay.portlet.documentlibrary.model.DLFileEntry) +(status:0))
(+(entryClassName:com.liferay.portlet.journal.model.JournalArticl­e) +(status:0))
) +
(+(groupId:10405) +(scopeGroupId:10405))
) +
(assetCategoryTitles:*Enterprise* assetCategoryTitles_nl_BE:*test* assetTagNames:*test*........

Thank you in advance.
Gepostet am 27.02.13 01:06 als Antwort auf Ray Augé.
Hello Ray,
Nice explanation. In CE 6.1, searching with "test_tag" among TAGS shows me no results and if i search with either "test" or "tag", no results are shown whereas single word tags are searched. After being through the search query, I found keywords with special characters are escaped and are searched as multiple keywords. The same search is working perfectly in 6.1EE.
Regards, Dileep.
Gepostet am 01.03.13 08:01.
Hi,
it seems that with 6.1.1 CE boolean operators stopped working.
With 6.1.0 following statements worked as expected:
my* NOT admin@mysite.com NOT service@mysite.com
Both users wasn't returned in the result set 6.1.0, but will be part of the result set in version 6.1.1.
Could anyone confirm this behaviour?

Best regards
Niklas
Gepostet am 08.04.13 04:17.
I have a problem with the fuzzy search.
I have implemented an indexer to index all the AssetTag.

the query is:
+(name:rembours~) +(entryClassName:com.liferay.portlet.asset.model.AssetTag)
I used the BooleanQueryFactoryUtil to create my BooleanQuery.

To test the lucene query, I also used luke and it works fine, it return 2 results.
But with liferay, the same query (and the same file index) return 0 results.
I used searchEngineUtil.search.
searchEngineUtil.search(searchContext.getSearchEngineId(­), PortalUtil.getDefaultCompanyId(), contextQuery, sorts, 0, nbrTag);
Gepostet am 26.04.13 07:24.
AssetTags are not indexed! your entryClassName value is not one which is ever indexed.
Gepostet am 26.04.13 07:27 als Antwort auf haikel thamri.
I have implemented a custom indexer in my custom Portlet, it index All AssetTags, I have tested it, it works fine and I tested my query with lucene!
Gepostet am 26.04.13 07:33 als Antwort auf Ray Augé.
Ok, can you give me some examples of indexed values that should be "near" enough to match?
Gepostet am 26.04.13 07:35 als Antwort auf haikel thamri.
Hi Ray,

I have implemented a custom indexer in my custom Portlet, it index All AssetTags, I have tested it, it works fine and I tested my query with lucene!

I have Implemented this method in my indexer
@Override
protected Document doGetDocument(Object obj) throws Exception {
AssetTag tag = (AssetTag) obj;

Document document = getBaseModelDocument(PORTLET_ID, tag);

document.addKeyword(Field.NAME, tag.getName());
document.addKeyword("tagId", tag.getTagId());

return document;
}
Gepostet am 26.04.13 07:37 als Antwort auf Ray Augé.
Sure, I got that part. Can you give me some examples of indexed values that "should" match the fuzzy term query above?
Gepostet am 26.04.13 07:40 als Antwort auf haikel thamri.
With luke
this query for example
+(name:routar*) +(entryClassName:com.liferay.portlet.asset.model.AssetTag)
return the AssetTag whose the name is "routard"
Gepostet am 26.04.13 07:42 als Antwort auf Ray Augé.
excuse me the query is
+(name:routar~) +(entryClassName:com.liferay.portlet.asset.model.AssetTag)
Gepostet am 26.04.13 07:42 als Antwort auf haikel thamri.
excuse me the query is
+(name:routar~) +(entryClassName:com.liferay.portlet.asset.model.AssetTag)
Gepostet am 26.04.13 07:42 als Antwort auf haikel thamri.
Ok, as soon as I get a chance will play with this to see where the issue might be.

In fact, if you have a ticket for this issue can you give me the ID for it? If there isn't one, can you create one with all the details here? (including the content and query example?

Thank you
Gepostet am 26.04.13 07:45 als Antwort auf haikel thamri.
Gepostet am 26.04.13 08:13 als Antwort auf Ray Augé.
Hi Ray,

Great post!! I'm having a few issues though... I can't seem to filter by categoryIds when I do a keyword search. It looks like this guy is having the same issue:

http://www.liferay.com/community/forums/-/message_boards/message/24311870

a­ny ideas?

Thanks in advance.

Brian
Gepostet am 02.05.13 14:23 als Antwort auf haikel thamri.
Hi,

Any progress on this. I have modified liferay's default Blog portlet via EXT to meet up my requirement.
In control panel when I click on Blogs portlet and try to search for a Blog with say "test" then I can see the list of Blogs with proper pagination.
For example , for 44 entries of corresponding Blogs I can see 3 pages i.e 4 links:
1 2 3 Next
But when I follow same step for my customized Blog portlet then for same results I can see 5 links:
1 2 3 4 Next
Now when I click on 4, no display appears with backend error saying :
java.lang.IllegalArgumentException: fromIndex(60) > toIndex(44)

Can anybody help me to find the exact cause. emoticon

Thanks
Gepostet am 03.06.13 00:22 als Antwort auf Firas BD.
Hi,

Any progress on this. I have modified liferay's default Blog portlet via EXT to meet up my requirement.
In control panel when I click on Blogs portlet and try to search for a Blog with say "test" then I can see the list of Blogs with proper pagination.
For example , for 44 entries of corresponding Blogs I can see 3 pages i.e 4 links:
1 2 3 Next
But when I follow same step for my customized Blog portlet then for same results I can see 5 links:
1 2 3 4 Next
Now when I click on 4, no display appears with backend error saying :
java.lang.IllegalArgumentException: fromIndex(60) > toIndex(44)

Can anybody help me to find the exact cause. emoticon

Thanks
Gepostet am 03.06.13 00:22 als Antwort auf Firas BD.
I am using sorting by a field in Webcontent structure which is multi world but the results get sorted by single terms and not the whole word
Gepostet am 12.06.13 10:17.
for anyone interested...This has been confirmed to be a bug in 6.1 GA2
Gepostet am 12.06.13 11:29 als Antwort auf Brian Scott Schupbach.
by "this" I mean "I can't seem to filter by categoryIds when I do a keyword search."
Gepostet am 12.06.13 11:30 als Antwort auf Brian Scott Schupbach.
Hello Ray,
Thanks for the great post.
I' m trying with the "Image Search Example" in your post but I don't get the image-only result. Any clues?

thanks
Gepostet am 14.06.13 08:28.
Is it possible to configure the faceted Search so that the user can find both journal-articles and only PDF-files from Documents and Media Library?
Gepostet am 04.09.13 04:21.
yes it can be done by selecting only these assests in search portlet's configuration
Gepostet am 04.09.13 10:35 als Antwort auf Bert Godon.
Please see https://www.liferay.com/web/raymond.auge/blog/-/blogs/faceted-search-and-customi­zed-filtering for how advanced filtering should be done!

HTH emoticon
Gepostet am 04.09.13 11:29 als Antwort auf Bert Godon.
H Ray,
I tried to add "com.liferay.portlet.polls.model.PollsQuestion" in Advanced Search Configuration, but my Polls are not returned in the search results.
Can you please show in an example how to do it for Polls ?

Thanks a lot.
Gepostet am 24.10.13 13:22.
It must be an entity which is indexed.
Gepostet am 24.10.13 13:24 als Antwort auf Nabil Bahtat.
Hi Ray,
How to make Polls portlet an indexed entity ?
Sorry for this question, I'm new to Liferay.

Thanks alot for your help.
Nabil
Gepostet am 28.10.13 23:21 als Antwort auf Ray Augé.
Minimally, you need to create and register an Indexer impl responsible for indexing and handling the indexed documents. Then you need to create a ServiceWrapper on the pols service which extends that service to index the polls when they are added/updated (or to retroactively index existing polls).

I won't lie, this is a fairly advanced (set of) task(s).
Gepostet am 29.10.13 09:23 als Antwort auf Nabil Bahtat.
I have a question about how the search is secured. I set up a test case as follows for a particular user:
--- Folder (no access)
------ Document (has access)

I confirmed that the user was unable to find the document in a search, but was able to see that a document existed with a facet count of 1.

Is this because two fundamentally different queries take place? The BaseIndexer.getFacetedSearch() method looks to be using the SearchPermissionChecker directly in the query, while it appears that the "regular" search is checking the permissions one-by-one by iterating over the hits in the BaseIndexer.filterSearch() method.

We are looking to implement our own search functionality, and are considering storing the View role IDs within the index itself to improve the search performance. Do you see any issues with this that we might want to be aware of, or are there specific "gotchas" that lead to the decision to check each document's permissions after the hits were found? Is this somehow less secure, and thus acceptable to display a facet hit count, but not to enforce overall document security?
Gepostet am 02.12.13 15:14.
Hi Ray,
I managed to do all the tasks about indexer you explained in your answer.
The problem is I don't know how to make my code availlable in Liferay.
What kind of Liferay project should I create (hook, ext plugin ...) ?

Thanks alot.
Gepostet am 12.01.14 11:24 als Antwort auf Ray Augé.
Is it possible to highlight the searchresult words with the components are related to searchContext or facets?
Gepostet am 13.03.14 07:00.
Hi Ray ,
we are passing facets as json . but range facet is not . even though date is passed as per the required syntax .
Can you please help on this :


stringBundler
.append("{"
+ "static: false, "
+ "order: 'OrderHitsDesc', "
+ "data: { "
+ "frequencyThreshold: 0, "
+ "ranges: [ {label:'modified', range:'[20140315000000 TO *]'}"
+ " ] "
+ "}, "
+ "className: 'com.liferay.portal.kernel.search.facet.RangeFacet', "
+ "fieldName: 'modified', " + "label: 'modified', " + "}");

stringBundler.append("]}");
Gepostet am 26.03.14 03:14 als Antwort auf lili samanta.
Hi Ray,
Could you please expand on the "paginationType" attribute for SearchContext, and what its possible values are/mean (seriously, what does "more" mean?)
Gepostet am 15.04.14 14:36.
Hi Ray,

We have requirement for search only users and in search result we need have select box to filter users on selected country.
Can you give any idea as I am new in liferay??

regards,
Nitin
Gepostet am 19.05.14 03:14.
Good Morning.

I need to make through faceted search, search Journal Articles with an specific structureId. I am trying as follows, but it does not quite work. Can you help me out?


{"facets": [
{
"displayStyle": "scopes",
"weight": 1.7,
"static": false,
"order": "OrderHitsDesc",
"data": {
"maxTerms": 10,
"frequencyThreshold": 1,
"showAssetCount": true
},
"label": "site",
"className": "com.liferay.portal.kernel.search.facet.ScopeFacet",
"fieldName": "groupId"
},
{
"displayStyle": "asset_entries",
"weight": 1.5,
"static": true,
"order": "OrderHitsDesc",
"data": {
"values": ["com.liferay.portlet.journal.model.JournalArticle"],
"frequencyThreshold": 0
},
"label": "asset-type",
"className": "com.liferay.portal.kernel.search.facet.AssetEntriesFacet",
"fieldName": "entryClassName"
},
{
"displayStyle": "asset_entries",
"weight": 1.5,
"static": true,
"order": "OrderHitsDesc",
"data": {
"values": ["36707"],
"frequencyThreshold": 0
},
"label": "asset-type",
"className": "com.liferay.portal.kernel.search.facet.MultiValueFacet",
"fieldName": "structureId"
}
]}



Thank you very much.
A greeting.
Gepostet am 28.10.14 01:10.
Hi Ray,
I have installed liferay 6.2 GA2 version bundled eith Tomcat and I'm trying to configure the Search portlet to be able to find Calendar Events.

I'm trying to find <indexer-class>com.liferay.portlet.calendar.util.CalIndexer</indexer-class> line inside liferay-portlet.xml within the sorce code of my portal but I haven't found it.

In the portal source code version I can see that class inside com.liferay.portlet.calendar.util package.

Could anybody give me a hand?

Has anybody faced this problem?

Thanks!!
Gepostet am 20.03.15 06:38 als Antwort auf Miguel González.
Because I believe what you are looking for is

https://github.com/liferay/liferay-plugins/blob/master/portlets/calendar-portlet­/docroot/WEB-INF/liferay-portlet.xml#L10

In 6.2 the calendar was heavily changed and mostly became a plugin.
Gepostet am 21.03.15 13:10 als Antwort auf Alba Garcia.
Thanks Ray!

I have imported the calendar-portlet from the plugin-sdk "liferay-plugins" on GitHub but I'm facing this issue related to Ivy:

"The ivy file '/home/usuario/github/liferay-plugins/portlets/calendar-portlet/ivy.xml' could not be parsed: Problem occurred while parsing ivy file: Unable to parse included ivy file for com.liferay#com.liferay.sdk;latest.integration in file:/home/usuario/github/liferay-plugins/portlets/calendar-portlet/ivy.xml"

Do you know what could be happening?

I'm not sure but Do you think that I could use the liferay-portlet.xml with the 6.2 GA2 calendar portlet version?

Thanks in advance!
Gepostet am 29.03.15 23:32 als Antwort auf Ray Augé.
Hi Ray,

In Liferay 7 M7, I found following shippet:
search.asset.type=com.liferay.portlet.blogs.model.BlogsEntry

OSGI-specifi­c. How to do it with classic portlets? Please see discussion at https://dev.liferay.com/web/liferay-7-community-expedition/feedback/-/message_bo­ards/message/560858

Thank you!
Gepostet am 24.08.15 13:15.