# Search

Location: [gRPC API](https://developer.m-files.com/APIs/gRPC-API/index.md) > [Concepts](https://developer.m-files.com/APIs/gRPC-API/index.md#concepts)

HTML version: https://developer.m-files.com/APIs/gRPC-API/concepts/search/

There are no folders to walk in a vault. To find objects you describe them with conditions and
call [SearchObjects](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCSearch/SearchObjects/index.md) (or
[GetObjectCountInSearch](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCSearch/GetObjectCountInSearch/index.md) to count them). A
search takes one array of conditions that must all match, returns only objects the caller may
see (for users who may see deleted objects, also deleted ones unless a condition excludes
them), and returns no property values.
The methods are in the [IRPCSearch](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCSearch/index.md) reference; the
[search guide](https://developer.m-files.com/APIs/gRPC-API/guides/search/index.md) builds a complete search step by step.

## The condition model

```text
SearchObjectsRequest
  conditions: [ SearchConditionArray ]       exactly one array
    value: [ SearchCondition, ... ]          all conditions must match (AND)
      expression  what to test     property 100 | status "is deleted" | any field (full text)
      type        how to compare   CONDITION_TYPE_EQUAL | _CONTAINS | _GREATER_THAN | ...
      value       compare to what  a TypedValue, like a property value
```

- A [SearchCondition](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.SearchCondition/index.md) is an
  [Expression](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.Expression/index.md), a [ConditionType](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.ConditionType/index.md) and a
  [TypedValue](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.TypedValue/index.md).
- The conditions of a [SearchConditionArray](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.SearchConditionArray/index.md) are ANDed. An
  array with no conditions matches every object the caller can see.
- Although `conditions` is a repeated field, `SearchObjects` accepts **exactly one** array:
  none, or two or more, fail with "The parameter is incorrect." The same holds for
  `GetObjectCountInSearch`.
- **OR within one property:** compare a lookup property `CONDITION_TYPE_EQUAL` to a multi-select
  lookup value that lists the alternatives. Class one-of (1, 2) in the Sample Vault returned 55
  objects, the 39 + 16 of the two classes. For other OR cases, run one search per alternative.

Expression kinds ([ExpressionType](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.ExpressionType/index.md)):

| Expression | Set | Use for |
| --- | --- | --- |
| `EXPRESSION_TYPE_PROPERTY_VALUE` | `data.property_value.property_def` | a property: class, title, dates, lookups |
| `EXPRESSION_TYPE_STATUS_VALUE` | `data.status_value.type` ([StatusType](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.StatusType/index.md)) | object type, ID, deleted, checked out |
| `EXPRESSION_TYPE_ANY_FIELD` | `data.any_field.options` ([FTSFLAGS](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.FTSFLAGS/index.md)) | full-text search, Aino search |
| `EXPRESSION_TYPE_TYPED_VALUE` | `data.typed_value` | any lookup to a value list, whichever property holds it |
| `EXPRESSION_TYPE_FILE_VALUE` | `data.file_value.type` | file name, size, has files |

An expression can also follow lookups to other objects ("documents whose project's customer is
X") with `Expression.indirection_levels`; see [IndirectionLevel](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.IndirectionLevel/index.md).

## Conditions you need most

Shown in protobuf text format. IDs above 1000 are from the Sample Vault.

```text
# Object type is Document (0): a lookup to the object type.
expression { type: EXPRESSION_TYPE_STATUS_VALUE
             data { status_value { type: STATUS_TYPE_OBJECT_TYPE } } }
type: CONDITION_TYPE_EQUAL
value { type: DATATYPE_LOOKUP
        data { lookup { value_list_item_info { obj_id { item_id { internal_id: 0 } } } } } }

# Not deleted. Add this to almost every search (see "What comes back").
expression { type: EXPRESSION_TYPE_STATUS_VALUE
             data { status_value { type: STATUS_TYPE_IS_DELETED } } }
type: CONDITION_TYPE_EQUAL
value { type: DATATYPE_BOOLEAN data { boolean: false } }

# Class (property 100) is 2, "Purchase Invoice".
expression { type: EXPRESSION_TYPE_PROPERTY_VALUE
             data { property_value { property_def: 100 } } }
type: CONDITION_TYPE_EQUAL
value { type: DATATYPE_LOOKUP
        data { lookup { value_list_item_info {
          obj_id { type: 1 item_id { internal_id: 2 } } } } } }

# Customer (property 1079, a multi-select lookup) includes customer 141. A single lookup
# value matches objects whose multi-select value contains it.
expression { type: EXPRESSION_TYPE_PROPERTY_VALUE
             data { property_value { property_def: 1079 } } }
type: CONDITION_TYPE_EQUAL
value { type: DATATYPE_LOOKUP
        data { lookup { value_list_item_info {
          obj_id { type: 136 item_id { internal_id: 141 } } } } } }

# Title (property 0) contains "ups". Text comparisons ignore case.
expression { type: EXPRESSION_TYPE_PROPERTY_VALUE
             data { property_value { property_def: 0 } } }
type: CONDITION_TYPE_CONTAINS
value { type: DATATYPE_TEXT data { text: "ups" } }

# Last modified (property 21) on or after 2012-01-01T00:00:00Z.
expression { type: EXPRESSION_TYPE_PROPERTY_VALUE
             data { property_value { property_def: 21 } } }
type: CONDITION_TYPE_GREATER_THAN_OR_EQUAL
value { type: DATATYPE_TIMESTAMP data { timestamp { seconds: 1325376000 } } }

# One object: type 136, ID 142. STATUS_TYPE_OBJECT_ID alone would also match document 142.
expression { type: EXPRESSION_TYPE_STATUS_VALUE
             data { status_value { type: STATUS_TYPE_OBJECT_TYPE_AND_ID } } }
type: CONDITION_TYPE_EQUAL
value { type: DATATYPE_LOOKUP
        data { lookup { value_list_item_info {
          obj_id { type: 136 item_id { internal_id: 142 } } } } } }

# Full text in metadata and file contents.
expression { type: EXPRESSION_TYPE_ANY_FIELD
             data { any_field { options { search_metadata: true search_filedata: true } } } }
type: CONDITION_TYPE_CONTAINS
value { type: DATATYPE_TEXT data { text: "invoice" } }
```

A full-text condition must set `search_metadata`, `search_filedata` or both; with neither, the
call fails with "Invalid search condition." Setting `FTSFLAGS.search_aino` instead runs an Aino
(semantic) search, which needs an enabled Aino index in the vault: without one the call fails
with "An enabled Aino index must be present to make an Aino Search." Aino results carry the
matching text passage in `SearchResultsItem.chunk`, but not the class or the object version, and
their file version is reported as 1: read the objects before using those values (see
[SearchObjects](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCSearch/SearchObjects/index.md)).

## What comes back

- **Only what the caller may see.** Results are filtered by permissions without any error: the
  same class search returned 0 contracts to a normal user and 13 to an administrator.
- **Deleted objects, for some users.** A user who can see deleted objects (a vault
  administrator, for example) gets them too unless the conditions exclude them: 66 versus 65
  results for one class in the Sample Vault. Add the "not deleted" condition.
- **One version per object**: the latest checked-in version, or the checked-out version when
  the object is checked out to the caller. `SearchFlags.look_in_all_versions` searches all
  versions instead.
- **No property values.** Each [SearchResultsItem](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.SearchResultsItem/index.md) has an
  `ObjectVersionEx` (IDs, version, title, class, files) and a relevance `score`. Read properties
  with
  [GetObjectVersionAndPropertiesOfMultipleObjects](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjectVersionAndPropertiesOfMultipleObjects/index.md).

## Limits, timeouts, sorting and paging

- `limit`: the maximum number of results; 0 means no limit, apart from a maximum the vault
  administrator may configure. `has_more_results` is true when more objects matched than were
  returned. The Sample Vault had 226 documents for a normal user: `limit` 10 returned 10 with
  `has_more_results` true; `limit` 0 returned all 226.
- `timeout_in_seconds`: 0 means no timeout, apart from a configured maximum.
- `sorting` ([SearchResultsSorting](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.SearchResultsSorting/index.md)): one
  [SortRule](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.SortRule/index.md) at most. `key` is a property definition ID (21 sorts by
  last modified; `sort_descending` reverses), or -102 for the object ID (ascending only). An
  unsupported sort (two rules, a multi-line text property, -102 descending) fails with "The
  content can't be sorted across all pages." unless
  `options.allow_resorting_to_default_sort` is true; then the results come in relevance order
  and the response has `resorted_to_default_sort` set.
- **Paging.** `page_requests` is not supported ("Not implemented."). Page with the object ID
  instead: sort by key -102 and add a `STATUS_TYPE_OBJECT_ID` condition
  `CONDITION_TYPE_GREATER_THAN` the last ID received (start with 0), until `has_more_results`
  is false. With `limit` 100 this read the 226 documents in pages of 100, 100 and 26. Sorting
  by object ID does not work together with a full-text condition. The
  [paging guide](https://developer.m-files.com/APIs/gRPC-API/guides/paging/index.md) has the complete loop.
- `facet_filter` narrows a full-text search by facet values for UIs that show facets; it is
  JSON and works with [GetFacetValues](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCSearch/GetFacetValues/index.md).

## Errors

Search errors come back with gRPC status `UNKNOWN` and the M-Files message as the status
details, for example "Invalid search condition." or "The parameter is incorrect."
([Errors](https://developer.m-files.com/APIs/gRPC-API/runtime/errors/index.md) shows how to read the error code). A condition
built with the wrong ID space usually does not fail: it just finds nothing, or finds the wrong
objects. When a search returns nothing, check the IDs against
[the ID spaces](https://developer.m-files.com/APIs/gRPC-API/concepts/vault-and-metadata-structure/index.md#the-id-spaces) first.
