<!-- Source: https://docs.squirro.com/en/latest/technical/search/features/query-syntax.html -->
# Query Syntax

Profiles: Project Creator, Search User

You can use query syntax within Squirro search bars to return better, more refined search results.

This page details the query syntax techniques available within Squirro.

Project creators can configure query syntax options. Search users can use the techniques outlined in this page to improve search accuracy.

Download the [`Advanced Query Syntax Cheat Sheet PDF`](../../../_downloads/695ba78502cfb95249e9c8f3406d9d8c/cheat-sheet-query-syntax-rev5.pdf) for a handy reference.

## Introduction

Per default, the `title` and `body` fields are taken into account when searching.

Sequences of query terms are combined using the OR operator, although the project’s configured _minimum-should-match_ strategy also applies.

Dynamically tagged text `labels` can also be configured to be searchable.

Reference: For details, see [How To Use Best-Bets Labels to Map Query Terms](../how-to-guides/how-best-bets.md#search-how-best-bets).

## Boolean Operators

Use `AND`, `OR`, `NOT`, `+` (plus sign) or `-` (minus sign) to explicitly combine terms. Be aware that the operators need to be in all capital letters.

The following restrictions apply:

- The `+` or _required operator_ requires that the term after the `+` symbol exists somewhere.
- The `-` or _prohibit operator_ excludes documents that contain the term after the `-` symbol.

### Example Boolean Queries

| Query | Description |
| --- | --- |
| `squirro AND memonic` | Search documents that contain squirro and memonic. |
| `squirro OR memonic` | Search documents that contain either squirro or memonic. |
| `+memonic -squirro` | Search documents that contain memonic but do not contain squirro. |
| `squirro NOT memonic` | Search documents that contain squirro but do not contain memonic. |

## Grouping

Use round brackets / _parentheses_ for grouping.

### Example Grouping Queries

| Query | Description |
| --- | --- |
| `(java AND solr) OR (python AND elasticsearch)` | Search documents that contain both java and solr, or documents that contain both python and elasticsearch. |
| `nektoon AND (squirro OR memonic)` | Search documents that contain nektoon and either squirro or memonic. |

## Phrase Search

Use double quotes at the beginning and ending of a phrase to perform a phrase search. Phrase search is useful to make the search results more precise by making sure that terms have to be found within close distance (per default the distance is set to 5 terms).

You can also add a slop to the phrase with a tilde `~` to manually specify the allowed distance between terms.

Note: The tilde operator only works with phrase searches, not other types of queries.

### Proximity Operators

Squirro supports three types of proximity operators for phrase searches:

- **Standard slop** (`~N`): Allows terms to be out of order with edit distance penalty. Swapping two words counts as 2 edits.
- **In-order proximity** (`~[N]`): Terms must appear in the specified order, with up to N words between them.
- **Out-of-order proximity** (`~(N)`): Terms can appear in any order, with up to N words between them.

### Example Phrase Search Queries

| Query | Description |
| --- | --- |
| `"oracle financial services"~1` | Find documents where oracle, financial and services match in exact this order and within three terms. |
| `"oracle financial leasing"~3` | Find documents where oracle, financial and leasing must match but allow for up to 3 additional terms between them. The order of the terms is no longer strict, but swapping two words is equivalent to adding two words in terms of edit distance. |
| `"oracle financial services"~[2]` | Find documents where oracle, financial and services must appear **in this exact order**, with up to 2 words between them. Uses Elasticsearch span queries for precise matching. |
| `"oracle financial services"~(3)` | Find documents where oracle, financial and services can appear **in any order**, with up to 3 words between them. More flexible than standard slop. |
| `"oracle financial services"` | Find documents where oracle, financial and services are found within the configured default `phrase_slop` distance. See project’s query strategy configuration (`topic.search.query-strategy::phrase.phrase_slop`) |

### Phrase Search in Specific Fields

When searching for phrases in specific analyzed fields (like `$title`, `$body`, `$summary`), you need to use **escaped double quotes** because the field value itself must be quoted as a delimiter.

The syntax uses two levels of quotes:

- **Outer quotes**: Delimit where the field value starts and ends
- **Inner escaped quotes** (`\"`): Indicate that the value should be treated as a phrase

Examples:

| Query | Description |
| --- | --- |
| `$title:"\"oracle financial services\""` | Search for the exact phrase “oracle financial services” in the title field |
| `$title:"oracle financial services"~2` | Phrase search in title with slop of 2. Proximity operators (`~N`, `~[N]`, `~(N)`) mark the query as a phrase, so escaped quotes are not needed |
| `$title:"oracle financial services"~[2]` | Phrase search in title with in-order proximity, requiring words in exact order with up to 2 words between. The proximity operator indicates a phrase, so escaped quotes are not needed |
| `$title:"oracle financial services"~(3)` | Phrase search in title with out-of-order proximity, allowing any order with up to 3 words between. The proximity operator indicates a phrase, so escaped quotes are not needed |
| `$title:["\"oracle financial services\"", report]` | Search for documents where title contains either the phrase “oracle financial services” or the term “report” |
| `$title:["quick brown fox"~2, "lazy dog"]` | Search for documents where title contains either phrase. When proximity operator is present, escaped quotes are optional (simpler syntax) |
| `$title:["quick brown"~[2], "lazy dog"~(1)]` | Search for documents where title contains either phrase with different proximity operators. Proximity operators make escaped quotes optional |

> **Note**
>
> For **keyword fields** (like `status` or custom labels), regular double quotes work without escaping since these fields
> don’t use phrase analysis. For example: `status:"in progress"` searches for the exact value “in progress”.

## Wildcard Search

Find documents that contain terms matching a wildcard pattern. Wildcard term matching is applied on title, body, and searchable Labels.

Two wildcard operators are supported:

- `*`, which matches zero or more characters
- `?`, which matches any single character

Avoid using wildcard queries with leading `*` or `?` patterns. This can increase iterations needed to find matching terms and thus cause very slow search performance.

### Example Wildcard Queries

|  |  |
| --- | --- |
| Query | Description |
| `squirr*` | Search documents that contain e.g. for squirro and squirrel. |
| `*emonic` | Search documents that contain e.g. for memonic and mnemonic. |
| `te?t` | Search documents that contain e.g. for test and text. |
| `name:*` | Search documents that have e.g. the field “name” 1 |
| `-name:*` | Search documents that do not have e.g. the field “name” 1 |
| `name:squir*` | Search documents that contain the “name” field started by “squir”, e.g. name:squirro and name:squirrel. 1 |

1 Note that label names containing spaces need to be put inside quotes in queries

## Field Search

Only search in specific fields, see examples below:

| Query | Description |
| --- | --- |
| `$title:France` | Search documents that have the term France in the title |
| `$body:France` | Search documents that have the term France in the document body |
| `$item_id:PgnAQM1FTSCP1uNOesoE7Q` | Search for a specific document by id |
| `$item_created_at>="2023-02-15T00:00:00"` | Search documents created after Feb. 14, 2023 |
| `$item_created_at<"2015-02-01T00:00:00"` | Search documents created before Feb. 1, 2015 |
| `$item_created_at>="now-7d/d"` | Search documents created in the last 7 days (see Elasticsearch Documentation ) |
| `$_size > 100000` | Search documents with size > 100’000 bytes |
| `$link:"<url here>"` | Search documents including a specific url. Url must be in quotes. |
| `$item_language:de` | Search documents written in a specific language. Use two-letter ISO 639-1 language codes, such as `de` for German or `en` for English. |

## Label Search

Use any document label to restrict the search, see examples below:

|  |  |
| --- | --- |
| Query | Description |
| `Country:France` | Search documents that have a label named Country with a value France |
| `Country:"United Kingdom"` | Search documents that have a label named Country with a value United Kingdom |
| `Country:[France, "United Kingdom"]` | Search documents where Country is France or United Kingdom (multi-value search) |

> **Note**
>
> Multi-value search syntax `field:[value1, value2, ...]` matches documents where the field contains
> **any of** the specified values. This works with both keyword fields (labels) and text fields
> (`$title`, `$body`, `$summary`). For text fields, the search properly handles word variations,
> synonyms, and language-specific analysis. For keyword fields, it generates an efficient as-is match.
>
>
>
> For bounded ranges (`field:[a TO b]`), see the [Range Search](#search-query-syntax-range) section.

Important: Label search is case sensitive.

## Range Search

Use Lucene-style bracket syntax to find documents where a numeric or date field falls within a bounded range. Square brackets `[ ]` make the bound inclusive, curly braces `{ }` make it exclusive, and the two styles can be mixed. Use `*` on either side to leave that side unbounded.

The `TO` keyword is case-insensitive, so `[5 TO 100]`, `[5 to 100]`, and `[5 To 100]` are all valid.

### Example Range Queries

| Query | Description |
| --- | --- |
| `price:[5 TO 100]` | Find documents where `price` is between 5 and 100, inclusive on both sides. |
| `price:{5 TO 100}` | Find documents where `price` is strictly greater than 5 and strictly less than 100. |
| `price:[5 TO 100}` | Mixed bounds: greater than or equal to 5, strictly less than 100. |
| `price:[* TO 100]` | Find documents where `price` is less than or equal to 100 (lower bound open). |
| `price:[5 TO *]` | Find documents where `price` is greater than or equal to 5 (upper bound open). |
| `$modified_at:["2024-01-01" TO "2024-12-31"]` | Find documents modified in 2024. Quote each side when the value contains a colon. |

Combine range queries with other operators as usual:

```text
$modified_at:["2024-01-01" TO "2024-12-31"] AND Country:France
```

> **Note**
>
> For fields that can hold several values per document, a bounded range query is not equivalent to combining individual comparison operators with `AND`. The expression `field:[a TO b]` requires the same value to satisfy both bounds, while `field > a AND field < b` is satisfied when any value is greater than `a` and any other value is less than `b`. For bounded ranges on multi-value fields, use the range syntax.

## Term-Level Boosting

> **Note**
>
> This feature only boosts individual terms or facets, to boost the full query clause see [Boosting Queries By Optional Ranking Signals](#query-level-boosting).

Individual elements of a query can be prioritized by boosting them. Note that sorting needs to be by relevance to notice the changed relevance scores.

### Example Boosted Queries

|  |  |
| --- | --- |
| Query | Description |
| `France^10 Europe` | Search for France and Europe, but boost matches of “France”. |
| `France OR Country:France^10` | Search for France in full text, as well as the “Country” label and boost items that have the value defined in the country label. |
| `France^0.1 Europe` | Search for France and Europe, but de-prioritize matches of “France” (the default boost is 1.0). |

## Sorting

You can use the following query syntax to sort the result:

```text
sort:<field_name>[:<order>]
```

Where `<field_name>` is either `date` (default) or `relevance` or any item field name you want to sort by and `<order>` is either `asc` for ascending or `desc` for descending. The order suffix is optional, the default order is descending.2

Additionally, you can add a second (or third etc) sorting criteria by adding

```text
[;<2nd_sort_field>[:<2nd_order>]]
```

to the query syntax.

2 Note: The square brackets above mean that those fields are optional. Those brackets are not part of the syntax.

### Example Sorting Queries

|  |  |
| --- | --- |
| Query | Description |
| `sort:date` | Sort by date (descending order by default) |
| `sort:date:asc` | Sort by date in ascending order |
| `sort:relevance:desc` | Sort by relevance in descending order |
| `sort:my_sortable_facet:desc;date:desc` | Sort by “my_sortable_facet” in descending order; additionally add a second sorting by descending date |
| `(Moon landing) sort:date` | Sort query by date (default order is descending) |

### Multiple Sorting Criteria

Squirro supports multiple sorting criteria, meaning that when multiple items match a criteria (e.g. the exact date), the next sorting criteria is then applied to those items.

In terms of syntax, the sorting criteria are applied in the order defined in the query. The first sorting criterion is the primary one; the second sorting criterion is the secondary one, and so on.

For example, if you use the syntax `sort:date:desc sort:$title:asc`, Squirro will first sort results by date in descending order, and then sort by title in ascending (alphabetical A-Z) order.

## Time Increment

It is possible to control the time increments shown in the main timeline and in the dashboard widgets. To do so, add `time_increment:<value>` to a query.

Here is the Bugzilla Project without a time_increment set:

[![image1](https://s3.amazonaws.com/download.squirro.net/docs/migrated-attachments/2949295/27394067.png)](https://s3.amazonaws.com/download.squirro.net/docs/migrated-attachments/2949295/27394067.png)

The same query, with time_increment:year

[![image2](https://s3.amazonaws.com/download.squirro.net/docs/migrated-attachments/2949295/27394068.png)](https://s3.amazonaws.com/download.squirro.net/docs/migrated-attachments/2949295/27394068.png)

Possible values are:

```text
time_increment:minute
time_increment:hour
time_increment:day
time_increment:week
time_increment:month
time_increment:quarter
time_increment:year
```

This can also be combined with values for more flexibility. For example:

```text
time_increment:12hours
time_increment:4days
time_increment:8weeks
time_increment:6months
time_increment:3year
```

There is a performance impact when using a time increment that results in many individual increments. This impact is both in the user interface, where each increment needs to be drawn, as well as on the Elasticsearch level, where they need to be calculated. So use the `time_increment` setting carefully.

## Entity Search

> **Note**
>
> Entity search should only be performed by Project Creators with access to the Entities page (under Setup→Explore). You must know the exact entity name to perform Entity search.

Query syntax to search for items having entities satisfied some criteria:

```python
entity:{< any query to match a single entity document >}
```

Example:

- Search for _Items_ containing a specific _Entity_ of type company:

  ```python
  entity:{type:company AND name:"Thomson Reuters"}
  ```
- Search for _Items_ containing at least one company-typed _Entity_ “Thomson Reuters” and another one _Entity_ “Squirro”:

  ```python
  entity:{type:company AND name:"Thomson Reuters"} AND entity:{type:company AND name:Squirro}
  ```
- Search for _Items_ containing a specific _Entity_ of type company with a confidence higher than 80%:

  ```python
  entity:{type:company AND name:"Thomson Reuters" AND confidence > 0.8}
  ```
- Search for _Items_ containing any _Entity_ of type company with confidence higher than 70%:

  ```python
  entity:{type:company AND NOT confidence < 0.7}
  ```
- Search for _Items_ containing no _Entity_ of type company with confidence higher or equal than 20%:

  ```python
  entity:{type:company AND confidence < 0.2}
  ```
- Search for _Items_ containing any _Entity_ of type deal with at least a 70% confidence:

  ```python
  entity:{type:deal AND confidence > 0.7}
  ```
- Search for _Items_ containing a specific _Entity_ of type deal:

  ```python
  entity:{type:deal AND properties.size:100 AND properties.region:US AND properties.industry:Tech AND properties.target:Whatsapp AND properties.acquirer:Facebook}
  ```
- Search for _Items_ containing one _Entity_ with target Squirro and another _Entity_ with target Whatsapp:

  ```python
  entity:{type:deal AND properties.target:Squirro AND properties.industry:Tech} AND entity:{type:deal AND properties.target:Whatsapp AND properties.industry:Tech}
  ```
- Search for _Items_ containing an _Entity_ of type deal with a property size bigger than 100:

  ```python
  entity:{type:deal AND properties.size > 100}
  ```

## Bookmarked and Read Items

Bookmarked items are items that users have added to their Bookmarks collection. The query syntax uses the legacy `starred` keyword for backward compatibility with the previous starred system.

Note: You need to enable flags for your project(s) before you can query for bookmarked and read items. To do so, set the `enable_flags_for_project_ids` property in `topic.ini`. For more details, see [topic.ini](../../admin/configuration/config-files/topic-ini.md#admin-topic-ini).

Query syntax for bookmarked and read items:

```python
is:starred      # Items in the user's Bookmarks collection
is:unstarred    # Items not in the user's Bookmarks collection
is:read         # Items marked as read
is:unread       # Items not marked as read
```

## Scoring Profiles and Queries

### Accessing Scoring Profiles

Scoring profiles use document metadata as additional filtering criteria to return the most relevant documents (according to the scoring profile).

Reference: For an introduction to scoring profiles see [How to Use Scoring Profiles to Customize Document Relevancy Scoring](../how-to-guides/how-relevancy.md#search-how-relevancy).

Those profiles can be directly used in the query syntax using the `profile:{}` literal.

Scoring profiles can either reference a configured profile from the project configuration by name or leverage a plugin without any project configuration required.

#### Out-of-the-Box Plugins

Plugins shipped out of the box by Squirro include the following:

- `is_new`: marks items as new when created after the user’s last browsing session. Requires activity tracking.
- `last_read`: boosts a user’s recently read items. The more recent the item was read, the higher the score.
- `popular_item`: boosts popular items. The more popular the item within a project, the higher the score.
- `concept`: runs concept search from within the search bar.
- `recommend_on_searches`: recommend items based on users’ search histories.
- `subscribed_communities`: add community filter queries for a user’s subscribed communities.
- `recency_boost`: make recent documents more relevant.

Example: For more information about these plugins, see [Scoring Plugins](../relevancy/scoring-plugins/index.md#search-scoring-plugins).

#### Example Queries

The examples below show how different scoring profiles can be referenced in the search bar:

Identify New Items

```bash
# Mark items as new with default settings (1 hour minimum session age)
profile:{ is_new }

# Configure minimum session age (only consider sessions older than 2 hours)
profile:{ is_new min_session_age:2h }

# Use different time units for session age
profile:{ is_new min_session_age:1d }    # 1 day
profile:{ is_new min_session_age:30m }   # 30 minutes

# Combine with keyword search to find new items matching a topic
technology profile:{ is_new }
```

The `is_new` profile adds a `new` flag to the `runtime_labels` field for items created after the user’s last browsing session. The `min_session_age` parameter specifies the minimum age of a session to be considered for calculating the last activity date.

This profile is useful for:

- Highlighting fresh content for returning users.
- Creating “what you missed” views.
- Surfacing recently ingested items.

The `is_new` functionality requires activity tracking to be enabled in the monitoring project. Without activity tracking, this profile has no effect.

For detailed information about new items, see the [Read, Unread, New, and Bookmarked Items](../../ui/items-interaction.md#ui-items-interaction) page.

Filter by Last Read Items

```bash
# Filter on last read user items with default settings
profile:{ last_read }

# Filter on last 5 read user items
profile:{ last_read count:5 }

# Filter on last 50 read user items
profile:{ last_read count:50 }

# Combine last read filter with keyword search
artificial intelligence profile:{ last_read count:20 }
```

The `last_read` profile filters items to show only those the current user has read. The profile boosts more recently read items higher in the results. The `count` parameter controls the maximum number of read items to return.

This profile is useful for:

- Finding items the user read previously.
- Building reading history views.
- Creating personalized dashboards based on user activity.

The last read functionality tracks both the timestamp when items were read and the count of read events per item. This tracking enables sophisticated user activity analysis and personalized content recommendations.

For detailed information about read and bookmarked items, see the [Read, Unread, New, and Bookmarked Items](../../ui/items-interaction.md#ui-items-interaction) page.

Date Time recency Boosting

```bash
# Boost documents by their item_creation date (default date field ranking)
profile:{ recency_boost }

# Boost documents by a custom date_time label, for example `last_updated`
profile:{ recency_boost date_field:last_updated }
```

Combinations of profiles

```bash
# Search for specific documents within users search history, and boost resulting items by their date recency
elasticsearch tutorial profile:{ last_read count:1000 } profile:{ recency_boost }

# Run concept search on a given text with additional boosting of recently trendy items
profile:{ concept text:"covid outbreak" } profile:{ popular_item last_months:1 }

# Filter documents that belong to user's subscribed communities, and boost the resulting items by their date recency
profile:{ subscribed_communities } profile:{ recency_boost }--------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
```

### Boosting Queries By Optional Ranking Signals

> **Warning**
>
> This feature only works if sort by relevancy is applied (`sort:relevance`)

In addition to ranking by profile, it is also possible to augment scoring by incorporating extra query clauses using the `rank_by:{}` and `scale_by:{}` literals.

These query clauses do not have to match a document for the document ot be retrieved, but matching documents receive a boost to their relevance score.

`rank_by:{}` clauses can be used to incorporate queries which will contribute to the total query score an additional score equal to the score of the wrapped query for each document (additive contribution).

`scale_by:{}` clauses can be used to incorporate queries which, when matched, will cause the final score of a scored document to be the overall query score multiplied by a factor defined by the magnitude assigned to this specific clause.

Note that these score boosting clauses, even when nested inside grouped clauses under some boolean structure, will instead still apply on the whole query.
Thus `` (wifi rank_by:{source:official}) OR (login rank_by:{source:unofficial}) `` will yield results that match the terms `wifi` or `login` and will augment the score of documents that are tagged as `official` or `unofficial` in the source field.

#### Example Queries

| Query | Description |
| --- | --- |
| `cheese rank_by:{ Country:France^10 }` | Search for the term `cheese` but boost items that additionally are tagged with `Country:France`. The final score per document is the score for the term `cheese` added to the score for the country tag (which is multiplied by 10 before being added). Items that don’t match `France` are still returned. |
| `wifi login rank_by:{ source:official^5 OR is_faq:True^10}` | Search for the term sequence `wifi login` with most important relevancy signal beeing `is_faq` and the second signal being items coming from the `official` named datasource. |
| `rank_by:{ entity:{"properties.Sentiment":"negative"} } rank_by:{ source:official^5 OR is_faq:True^10}` | Boost items that are tagged on sentence level with a classification output (`entities`), in this case `negative` sentiment. |
| `arbitrage scale_by:{ $item_created_at>="2023-01-01" }^2` | Search for the term `arbitrage` and boost the score of documents that are created after 2023 by a factor of 2 |

It’s also possible to use scoring profiles within the `rank_by` clause to enable use-case-specific ranking, for example on the dashboard or widget level.

|  |  |
| --- | --- |
| Query | Description |
| `rank_by:{ profile:{plugin:last_read $last_days:7} }` | Match all available items in the project, but boost the user’s recently-read items according to read time. The more recent, the more relevant. |

## Cheat Sheet

Download the [`Advanced Query Syntax Cheat Sheet PDF`](../../../_downloads/695ba78502cfb95249e9c8f3406d9d8c/cheat-sheet-query-syntax-rev5.pdf) shown in the image below for a handy reference guide.

[![Image of the Advanced Query Syntax Cheat Sheet](https://s3.amazonaws.com/download.squirro.net/docs/technical/products/aqs-cheat-sheet.png)](https://s3.amazonaws.com/download.squirro.net/docs/technical/products/aqs-cheat-sheet.png)
