# Query custom data This library provides several query APIs that support custom data integration. 1. `Query` - [Query contacts (advanced)](./../basics/query-contacts-advanced.md) 2. `BroadQuery` - [Query contacts](./../basics/query-contacts.md) 3. `RawContactsQuery` - [Query contacts](./../basics/query-raw-contacts.md) 4. `ProfileQuery` - [Query device owner Contact profile](./../profile/query-profile.md) 5. `DataQuery` - [Query specific data kinds](./../data/query-data-sets.md) To help illustrate how custom data integrates with these query APIs, we'll use the `HandleName` and `Gender` custom data. > ℹ️ For more info, read [Integrate the gender custom data](./../customdata/integrate-gender-custom-data.md) > and [Integrate the handle name custom data](./../customdata/integrate-handlename-custom-data.md). ## Getting custom data from a Contact or RawContact Custom data, just like regular data kinds, are attached to a RawContact. They follow the same rules as regular data kinds. > ℹ️ For more info, read about [API Entities](./../entities/about-api-entities.md). For example, you are able to get the handle names and gender of a RawContact, ```kotlin val handleNames = rawContact.handleNames(contactsApi) val gender = rawContact.gender(contactsApi) ``` There are also extensions that allow you to get custom data from a Contact, which can be made up of one or more RawContacts, ```kotlin val handleNames = contact.handleNames(contactsApi) val genders = contact.genders(contactsApi) ``` ## Getting specific custom data kinds directly Every custom data provides an extension to the `DataQuery` that allows you to query for only that specific custom data kind. For example, to get all available `HandleName`s and `Gender`s from all contacts, ```kotlin val handleNames = Contacts(context).data().query().handleNames().find() val genders = Contacts(context).data().query().genders().find() ``` To get all `HandleName`s starting with the letter "h", ```kotlin val handleNames = Contacts(context) .data() .query() .handleNames() .where { Handle startsWith "h" } .find() ``` For more info, read [Query specific data kinds](./../data/query-data-sets.md). ## The `include` function and custom data All of the above mentioned APIs provide an `include` function that allows you to include only a given set of fields (data) in each of the returned entities. Custom data entries provides fields that can be used in this function. By default, not calling the `include` function will include all fields, including custom data fields. For example, to explicitly include all `HandleName` fields, ```kotlin .include(HandleNameFields.all) ``` For more info, read [Include only certain fields for read and write operations](./../basics/include-only-desired-data.md). ## The `where` function and custom data The `Query`, `RawContactsQuery`, and `DataQuery` APIs provides a `where` function that allows you to specify a matching criteria based on specific field values. Custom data entries provides fields that can be used in this function. For example, to match `HandleName`s starting with the letter "h", ```kotlin .where { Handle startsWith "h" } ``` The `BroadQuery` API provides a `wherePartiallyMatches` function that NOT support matching custom data. Only AOSP data are included in the matching process. The `ProfileQuery` API does not provide a where function as there can only be one profile Contact per device. ## The `orderBy` function and custom data The `DataQuery` API provides an `orderBy` function that supports custom data. For example, to order `HandleName`s, ```kotlin .orderBy(HandleNameFields.Handle.asc()) ``` The `Query`, `BroadQuery`, and `RawContactsQuery` APIs provides an `orderBy` function that only takes in fields from the Contacts/RawContacts table, not the Data table. So there is no custom data, or AOSP data, support for this. The `ProfileQuery` API does not provide an `orderBy` function as there can only be at most one profile Contact on the device.