Searching by custom field values

Example - Get a user based on an expando value

We know expando can be a bit confusing sometimes especially because one needs to understand the tables it requires to use the API. This can be confusing for someone that is learning Liferay or trying to develop their first custom field based feature.

In this post we will show you an example on how to use custom fields to locate assets in Liferay; we will be searching according to custom fields' values, instead of just accessing values.

The steps are simple:

  1. Get the column based on the field you want to search and the class that represents what you are searching
  2. Define the criteria for your query:
    1. The column is the one you got on step 1
    2. The class name ID should match the class of what you are searching
    3. The data should be equal to the value you have
  3. Get a projection to tell you what entities were found as a list of IDs
  4. Use the returned values to fetch the objects that effectively represent what you are looking for

Example

As an example we will try to answer this simple question following those steps: How to get users based on a custom field value?

Just as a note, we will be using the following static imports to keep the example short:


import static com.liferay.expando.kernel.service.ExpandoColumnLocalServiceUtil.getDefaultTableColumn;
import static com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil.forClass;
import static com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil.property;
import static com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil.forName;
import static com.liferay.portal.kernel.service.ClassNameLocalServiceUtil.getClassNameId;


Step 1: Get the expando column


ExpandoColumn column = getDefaultTableColumn( companyId, User.class.getName( ), fieldName );


Step 2: Define the criteria


Criterion columnIdCriterion = forName( "columnId" ).eq( column.getColumnId( ) );
Criterion classNameIdCriterion = forName( "classNameId" ).eq( getClassNameId( User.class.getName( ) ) );
Criterion valueCriterion = forName( "data" ).eq( fieldValue );


Step 3: Define the projection to build a query


Projection userIdProjection = property( "classPK" );


return forClass( ExpandoValue.class ).add( columnIdCriterion )
				.add( valueCriterion )
				.add( classNameIdCriterion )
				.setProjection( userIdProjection ); 


Steps 1-3: A summary method


	static DynamicQuery getValueQuery( long companyId, String fieldName, String fieldValue ) {

		ExpandoColumn column = getDefaultTableColumn( companyId, User.class.getName( ), fieldName );

		Criterion columnIdCriterion = forName( "columnId" ).eq( column.getColumnId( ) );

		Criterion classNameIdCriterion = forName( "classNameId" ).eq( getClassNameId( User.class.getName( ) ) );

		Criterion valueCriterion = forName( "data" ).eq( fieldValue );

		Projection userIdProjection = property( "classPK" );

		return forClass( ExpandoValue.class ).add( columnIdCriterion )
						.add( valueCriterion )
						.add( classNameIdCriterion )
						.setProjection( userIdProjection );
	}    


Step 4: Get your entities

The hard part is done, we just need to get our entities now. For that, we will use the query we built on steps 1 to 3 as a sub query.


	static DynamicQuery getUserQuery( long companyId, String fieldName, String fieldValue ) {

		DynamicQuery valueQuery = getValueQuery( companyId, fieldName, fieldValue );
		DynamicQuery userQuery = forClass( User.class );

		Criterion idCriterion = forName( "userId" ).in( valueQuery );

		return userQuery.add( idCriterion );
	}    


Execute

Finally! We can now execute the queries to get our lists!


	public static List< User > searchUsers( long companyId, String fieldName, String fieldValue ) {

		DynamicQuery query = getUserQuery( companyId, fieldName, fieldValue );

		return dynamicQuery( query );

	}    

More Blog Entries

0 Comments