Searching for Records
Search in the API using ResourceService.search()
, which provides similar functionality to search views in the TeamConnect user interface.
Because searching may drastically affect performance, verify that there is no other way to get the desired list of records. If you must conduct a search, especially against a large number of records, narrow your search criteria and consider providing a time-out.
Before using the search()
methods, consider using available predefined methods to get related records. For example, the User
interface has the getContact()
method to obtain the contact of a user. The Project
interface has methods for obtaining a list of child or involved records.
The following table provides examples of records that custom code is likely to includes as part of a search and whether or not an alternative exists.
To Search or Not to Search
If you are looking for |
Use search? |
Use this instead |
|
---|---|---|---|
Yes |
No |
||
All contacts. |
x |
||
Any documents (but not document folders). |
x |
||
Any history records. |
x |
||
Any of these system object records related records to a Project record:
|
x |
||
Child or embedded records of a |
x |
|
|
Child records of an |
x |
||
Current user. |
x |
|
|
Involved record associated with an account. |
x |
||
Old object. |
x |
|
|
Parent record of a related |
x |
|
|
Parent record of a related |
x |
|
|
Project of a related system object record. |
x |
|
|
Project record of an |
x |
|
|
Record to which a |
x |
|
|
Sub-objects. |
x |
Use the appropriate methods defined in the owner interface. For details, see Sub-Objects. |
Creating an API Search View
When you are creating code for searching, you must include the following information in your search code:
- One of three
ResourceService.search()
methods to execute the search.- A method that uses the search view key to return the results of a search view.
- A method that uses filter criteria to return search results.
- A method that uses filter criteria and search parameters to return search results.
- Methods part of the search classes to enter search criteria and parameters.
- The resource service class and concrete objects to specify the objects you are searching. For example, if you are searching for accounts, access
AccountService
so that you can useAccount
methods as part of the search.
When you include all this information, you can execute the search.
Search Criteria
Creating search criteria is the same as entering Filter Criteria for a custom search. To create filter criteria, use one of the two search()
methods that accept SearchCriteria
. Depending on your filter criteria, you can construct SearchCriteria
in one of three ways:
SearchCriteria()
—Searching for one type of record.SearchCriteria(FieldCriterion fieldCriterion)
—Searching with one filter criteria.SearchCriteria(SearchExpression expr1, SearchExpression expr2, SearchExpression... expressions)
—Searching with multiple filter criteria.
Searching for One Type of Record
To return all records of a specific type, use an empty SearchCriteria()
. For example, if you want to return all records for one project type, pass in the project's unique code and SearchCriteria()
, as shown in the following sample.
// Using an empty search criteria to return all Disputes List<Project> allDisputes = platform.getProjectService().search("DISP", new SearchCriteria());
Searching with One Filter Criteria
To search with one filter criteria, use SearchCriteria(FieldCriterion fieldCriterion)
. Use FieldCriterion
to enter the fields you are searching on and its subclasses when you know the data types of those fields. Along with the field, you include the value of the field that determines the search results.
For example, if you want to search for all appointments in Room 101, you can use the code in the following sample.
// Retrieve the appointment service from the platform provided by the API. AppointmentService appointmentService = platform.getAppointmentService(); // Find all appointments located in Room 101 StringCriterion locationCriterion = new StringCriterion(Appointment.LOCATION).equalTo("Room 101"); SearchCriteria criteria = new SearchCriteria(locationCriterion); // Execute search List<Appointment> results = appointmentService.search(criteria);
The previous sample uses the following code to build search criteria:
Appointment.LOCATION
for searching on a system field.equalTo("Room 101")
for setting the operator.
Searching with Multiple Filter Criteria
To search with multiple filter criteria, use SearchCriteria(SearchExpression expr1, SearchExpression expr2, SearchExpression... expressions)
. SearchExpression
allows you to search during the following scenarios.
All or Any Criteria as Part of the Results
You may want to search with more than one filter criteria and you want all or any of the criteria to be part of the results. For all the criteria, use the and()
method. For any of the criteria, use the or()
method.
The following code sample provides an example of using the or()
method to join date criteria and combining the date criteria with the and()
method.
// Retrieve the appointment service from the platform provided by the API. AppointmentService appointmentService = platform.getAppointmentService(); // Find all appointments located in Room 101 SearchCriteria criteria = new SearchCriteria(new StringCriterion(Appointment.LOCATION).equalTo("Room 101")); // Find appointments starting within four days or ending in the next two days RelativeDateCriterion startOnCriterion = new RelativeDateCriterion(Appointment.START_ON).next(4); RelativeDateCriterion endOnCriterion = new RelativeDateCriterion(Appointment.END_ON).next(2); // Join the two date criteria, specifying 'or' logic SearchCriteria dateCriteria = startOnCriterion.or(endOnCriterion); // Join the date criteria and location criteria criteria.and(dateCriteria); // Execute search and return results List<Appointment> results = appointmentService.search(criteria);
- The first search expression uses one filter criteria to specify that the results return all appointments in Room 101.
SearchCriteria criteria = new SearchCriteria(new StringCriterion(Appointment.LOCATION).equalTo("Room 101"));
- The second search expression specifies relative date criteria using the
next()
method and combines them with theor()
method to specify whether the search returns the applicable start date or end date.
RelativeDateCriterion startOnCriterion = new RelativeDateCriterion(Appointment.START_ON).next(4); RelativeDateCriterion endOnCriterion = new RelativeDateCriterion(Appointment.END_ON).next(2); SearchCriteria dateCriteria = startOnCriterion.or(endOnCriterion);
- The sample combines both of the previous expressions.
criteria.and(dateCriteria);
- The code executes.
List<Appointment> results = appointmentService.search(criteria);
Complex Criteria to Determine Results
You may want to specify whether some and which criteria should be, should possibly be, or should not be part of the results. You can use a different method for each search criteria:
- You can specify that the search must include two search conditions with
and()
. - You can specify that either search condition should appear in the search results using
or()
. - You can specify conditions for results that you do not want to include using
not()
.
The following code sample provides an example of the previous scenario.
// Get service AppointmentService appointmentService = platform.getAppointmentService(); // Group One: In Room 101 AND All Day StringCriterion locationCriterion = new StringCriterion(Appointment.LOCATION).equalTo("Room 101"); BooleanCriterion allDayCriterion = new BooleanCriterion(Appointment.ALL_DAY).isTrue(); SearchCriteria andGroup = locationCriterion.and(allDayCriterion); // Group Two: Started within the last 5 days OR ends in the next 3 days RelativeDateCriterion startOnCriterion = new RelativeDateCriterion(Appointment.START_ON).withinLast(5); RelativeDateCriterion endOnCriterion = new RelativeDateCriterion(Appointment.END_ON).next(3); SearchCriteria orGroup = startOnCriterion.or(endOnCriterion); // Composite Group: NOT in both group one and group two SearchCriteria notGroup = new SearchCriteria(andGroup, orGroup).not(); // Execute search and return results return appointmentService.search(notGroup);
The previous sample includes the following code:
- The first search expression specifies all day-long appointments in Room 101.
StringCriterion locationCriterion = new StringCriterion(Appointment.LOCATION).equalTo("Room 101"); BooleanCriterion allDayCriterion = new BooleanCriterion(Appointment.ALL_DAY).isTrue(); SearchCriteria andGroup = locationCriterion.and(allDayCriterion);
- The second search expression specifies all appointments that started in the last 5 days or end in the next 3 days.
RelativeDateCriterion startOnCriterion = new RelativeDateCriterion(Appointment.START_ON).withinLast(5); RelativeDateCriterion endOnCriterion = new RelativeDateCriterion(Appointment.END_ON).next(3); SearchCriteria orGroup = startOnCriterion.or(endOnCriterion); RelativeDateCriterion startOnCriterion = new RelativeDateCriterion(Appointment.START_ON).withinLast(5); RelativeDateCriterion endOnCriterion = new RelativeDateCriterion(Appointment.END_ON).next(3); SearchCriteria orGroup = startOnCriterion.or(endOnCriterion);
- The third search expression specifies all appointments not part of the other two expressions.
SearchCriteria notGroup = new SearchCriteria(andGroup, orGroup).not();
- The sample searches for all results that the third expression returns as part of its execution.
appointmentService.search(notGroup);
Note: This code uses the and(SearchExpression expression)
method instead of the and()
method because it combines multiple filter criteria with additional search expressions. If the AND or OR applies to all filter criteria, use the and()
or or()
methods.
When you have one field that is directly part of a record, you can construct a criterion with the SearchableField
.
Note: If the record does not have direct access to the field but can access it through a field in the record, you must construct a criterion with a FieldPath.
The type of criterion depends on the type of field. The API provides the following criterion types with SearchableField
constructors:
BooleanCriterion
—For Boolean fields.CategoryCriterion
—For categories.DateCriterion
—For date fields.DecimalCriterion
—For BigDecimal fields.EnumerationCriterion
—For enum-based fields.FieldCriterion
—For all fields.IntegerCriterion
—For integer fields.LookupItemCriterion
—For lookup table fields.ObjectCriterion
—For account, contact, project, and user fields.RelativeDateCriterion
—For integers before and after a certain date.StringCriterion
—For string fields.
The SearchableField
you use depends on whether the field is a system or custom field.
System Field Searching
When you want to search for a system field, use the static field in the model class for the object. You can find a list of static fields for each class in the javadocs: ~\utilities\javadocs\api\index.html
For example, if you are searching on the Location field in appointments, the LOCATION
static field is part of the Appointment class. As a result, the SearchableField
is Appointment.LOCATION
. Before you add the operator, the search field of the criterion looks like the following code.
StringCriterion locationCriterion = new StringCriterion(Appointment.LOCATION)
Custom Field Searching
When you want to search for custom fields, you can use the CustomField
class to retrieve information about fields for a search.
Note: When searching on system fields, use the static system fields in the class for that object. For example, to search with the Location field in appointments, use Appointment.LOCATION.
Use the CustomField
class when you have to include custom fields in search criteria. You can use this interface with custom fields of all data types. However, if you are working with projects, Involved parties, or lookup table custom fields, you have the following additional classes:
ProjectCustomField
LookupCustomField
InvolvedCustomField
The following code sample provides an example of how to search using a custom field as the search criteria.
// Get instances of the services we'll need ProjectService projectService = platform.getProjectService(); CategoryService categoryService = platform.getCategoryService(); // Retrieve the custom field CustomField<String> textField = categoryService.getCustomField("fullTreePositionofCategory", "customFieldName"); // Find records with the given custom field set to "Test value" StringCriterion stringCriterion = new StringCriterion(textField).equalTo("Test value"); SearchCriteria searchCriteria = new SearchCriteria(stringCriterion); // Execute search and return results return projectService.search(“DISP”, searchCriteria”);
Field paths contain more than one SearchableField
. Use FieldPath
to construct a field when the record does not have direct access to the field you want to search.
For example, if you want to search with the username of an appointment attendee, you cannot access the user directly from the appointment. The Appointment
class contains the static ATTENDEES field. Once you have access to the attendees, you can access the static USER field with the AppointmentAttendee
class. After you have access to the user, you can access the static USERNAME field with the User
class. As a result, the FieldPath
is (Appointment.ATTENDEES).add(AppointmentAttendee.USER).add(User.USERNAME)
;
Before you add the operator, the field path looks like the following code.
FieldPath fieldPath = new FieldPath(Appointment.ATTENDEES).add(AppointmentAttendee.USER).add(User.USERNAME );
The following code includes an example of a search with two criteria that use field paths.
AppointmentService appointmentService = platform.getAppointmentService(); // Create a path to the Appointment's Project's Created On FieldPath projectCreatedOn = new FieldPath(Appointment.PROJECT).add(Project.CREATED_ON); // Create a path to the Appointment's Attendee's Attendance Type FieldPath attendeeAttendanceType = new FieldPath(Appointment.ATTENDEES).add(AppointmentAttendee.ATTENDANCE_TYPE); // Search for appointments related to projects created in the last thirty days RelativeDateCriterion relativeDateCriterion = new RelativeDateCriterion(projectCreatedOn).withinLast(30); // Search for appointments that have attendees that will not attend EnumerationCriterion<AttendanceType> enumerationCriterion = new EnumerationCriterion<AttendanceType>(attendeeAttendanceType).equalTo(AttendanceT ype.WILL_NOT_ATTEND); // Criterions constructed from field paths behave exactly like criterions constructed from fields, and can be combined just the same SearchCriteria criteria = new SearchCriteria(relativeDateCriterion, enumerationCriterion); // Execute search List<Appointment> appointments = appointmentService.search(criteria);
You can also use field paths with custom field searching, as shown in the following sample.
ProjectService projectService = platform.getProjectService(); CategoryService categoryService = platform.getCategoryService(); // Field Paths can also point to custom fields CustomField<String> customField = categoryService.getCustomField("CONT", "custom field"); FieldPath contactCustomField = new FieldPath(Project.CONTACT).add(customField); // Search for projects based on contact custom field StringCriterion stringCriterion = new StringCriterion(contactCustomField).equalTo("value"); SearchCriteria criteria = new SearchCriteria(stringCriterion); // Execute search List<Project> projects = projectService.search("DISP", criteria);
Setting operators in the API are similar to setting operators in TeamConnect custom searches. To search with operators, use the FieldCriterion
class and all the classes that extend it. FieldCriterion
includes methods for operators that you can use on all fields.
Because each data type has different operators, each data type class has its own set of methods for using operators. These methods are part of the following classes:
BooleanCriterion
—Operators for Boolean fields.CategoryCriterion
—Operators for categories.DateCriterion
—Operators for date fields.DecimalCriterion
—Operators for BigDecimal fields.EnumerationCriterion
—Operators for enum-based fields.IntegerCriterion
—Operators for integer fields.LookupItemCriterion
—Operators for lookup table fields.ObjectCriterion
—Operators for account, contact, project, and user fields.RelativeDateCriterion
—Operators for integers before and after a certain date.StringCriterion
—Operators for string fields.
In the case of the example for system field searching without the operator, the entire criterion looks like the following code with the operator:
StringCriterion locationCriterion = new StringCriterion(Appointment.LOCATION).equalTo("Room 101");
Search Parameters
Use search parameters to control the search, such as the page size and the sort order of the search results. To control your search, use the search() method that accepts the SearchParameters
class.
As you create the code for searching, use the search parameter constructors. The constructors include a combination of the following search parameters:
beginIndex
—The first page of results the search returns.limit
—The number of search results to return on a page.useUnsavedChanges
—An indication of whether the search should run against changes not yet committed to the database.· sortFields—The fields for sorting the search results.-
sortFields
—The fields for sorting the search results.
If a constructor does not include one of these parameters, the search uses the default for the parameter. Retrieve or set the default settings using the SearchParameters
get and set methods (getBeginIndex()
, setLimit()
, etc.).
The following list provides examples of some SearchParameters constructors. For a full list of constructors, refer to the SearchParameters
class in the javadocs.
SearchParameters(SortField... sortFields)
You can specify how you want the search results to sort. This constructor creates a parameter with one or more sort fields, the default limit, and the default begin index. The following code sample sorts the results by start date in ascending order.
// Sort results by start date SearchParameters parameters = new SearchParameters(new SortField(Appointment.START_ON));
-
SearchParameters(java.lang.Integer limit)
You can limit the number of results in a search. This constructor creates a parameter with the number of search results, the default being index, and no sort fields. The following code sample limits the number of results to 10 records.
// Limit results to 10 records SearchParameters parameters = new SearchParameters(10);
-
SearchParameters(boolean useUnsavedChanges)
You can specify whether a search should return results from the database or changes not yet commented to the database. This constructor creates a parameter that specifies which to search, the default limit and begin index, and no sort fields. The following code sample specifies that the search results will include changes not yet saved to the database.
// Includes unsaved changes in search results SearchParameters parameters = new SearchParameters(true);
Executing a Search
When you have all the information you need to return search results, whether it is the search view key or the search criteria and parameters, you can execute the search.
The following code sample executes a search with search criteria and parameters. This sample returns search results for appointments in Room 101 sorted by start date.
public class AppointmentSample extends List<Appointment> { @Override public void action(Appointment appointment) { } public void searchAppointment() { // Retrieve the appointment service from the platform provided by the API. AppointmentService appointmentService = platform.getAppointmentService(); // Find all appointments located in Room 101 StringCriterion locationCriterion = new StringCriterion(new FieldPath(Appointment.LOCATION)).equalTo("Room 101"); SearchCriteria criteria = new SearchCriteria(locationCriterion); // Sort results by start date SearchParameters parameters = new SearchParameters(new SortField(new FieldPath(Appointment.START_ON))); // Execute search List<Appointment> results = appointmentService.search(criteria, parameters); } }