Query Syntax#
Profiles: Project Creator, Search User
You can use query syntax within Squirro search bars to return better, more refined search results.
Query syntax is the way you structure a search input. Operators (AND, OR, NOT, +, and -), brackets, wildcards (* and ?), and quotation marks let you narrow or broaden which documents match. Bookmarking, boosting, sorting, and time increments let you adjust how the matching results are presented.
This page details the query syntax techniques available within Squirro. To run the same queries from an integration and choose which item fields are returned, see the Search API page.
Project creators can configure query syntax options. Search users can use the techniques outlined in this page to improve search accuracy.
Defaults#
By default, the title and body fields are taken into account when searching.
A run of plain search terms is treated as one unit. Inside that unit the terms are combined with OR, and the minimum-should-match strategy configured for the project decides how many of them a document has to contain. A phrase, a field filter, or a group forms a separate unit, and units that sit next to each other are combined with AND.
For example, in one two "three four" the run one two is one unit and the phrase "three four" is another. The phrase has to match, while minimum-should-match decides whether one, two, or both are also required.
Dynamically tagged text labels can also be made searchable.
For more information, see the How To Handle User Query Terms Correctly page.
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. The term has to follow immediately, since- squirrowith a space is read as plain text.
Example query |
Description |
|---|---|
|
Search documents that contain squirro and memonic. |
|
Search documents that contain either squirro or memonic. |
|
Search documents that contain memonic but do not contain squirro. |
|
Search documents that contain squirro but do not contain memonic. |
Grouping#
Use parentheses to group terms, so that a Boolean operator applies to the whole group instead of to a single term. Grouping is what lets you combine AND and OR in one query without the result depending on operator precedence.
Example query |
Description |
|---|---|
|
Search documents that contain both java and solr, or documents that contain both python and elasticsearch. |
|
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 makes results more precise by requiring the terms to sit close together. How much slack they get is set by the project query strategy configuration (topic.search.query-strategy::phrase.phrase_slop), which ships as 0, meaning the terms have to be adjacent and in the order written.
For example, "oracle financial services" matches documents where those three terms appear together as written. Without the quotes, the same words are treated as separate terms, so a document matches even when they appear far apart or in a different order.
You can also add a slop to the phrase with a tilde ~ to manually specify the allowed distance between terms. For example, "oracle financial leasing"~3 allows up to three additional words between them in total.
Note
The tilde operator only works with phrase searches, not other types of queries.
Proximity Operators#
Three proximity operators are available for phrase searches. In all three, N is a whole number that sets how many extra words may sit between the terms, counted across the whole phrase rather than per gap. With more than two terms, that budget covers every gap together. The operators differ in how they treat terms that appear in a different order than written:
Standard slop (
~N)The terms can change order, but reordering spends the same budget. Swapping two neighboring words costs 2, so
~0and~1keep the order written.In-order proximity (
~[N])The terms must appear in the order written.
Out-of-order proximity (
~(N))The terms can appear in any order, and reordering them costs nothing.
Use ~[N] when the order of the terms matters, and ~(N) when it does not.
Example query |
Description |
|---|---|
|
Find documents where oracle, financial, and services appear in this order, with at most one extra word between them, so |
|
Find documents where oracle, financial, and leasing appear with up to 3 extra words between them in total. The terms can also appear in a different order when the budget allows, since swapping two neighboring words costs 2. |
|
Find documents where oracle, financial, and services must appear in this exact order, with up to 2 words between them in total. |
|
Find documents where oracle, financial, and services can appear in any order, with up to 3 words between them in total. |
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
A
\"on each side of the series of words marks those words as a phrase.
Example query |
Description |
|---|---|
|
Search for the exact phrase |
|
Phrase search in title with slop of 2. The proximity operator indicates a phrase, so escaped quotes are not needed. |
|
Search for documents where title contains either the phrase |
|
Search documents where title contains the phrase |
Keyword fields, such as status or a custom label, do not use phrase analysis, so regular double quotes work there without escaping. For example, status:"in progress" searches for the exact value in progress.
Wildcard Search#
Find documents that contain terms matching a wildcard pattern. Wildcard matching applies to the title, the body, and searchable labels.
Two wildcard operators are supported:
Asterisk
*matches zero or more characters. Because it also matches nothing,squirr*matchessquirritself as well assquirroandsquirrel.Question mark
?matches exactly one character, which has to be present.te?tmatchestestandtext, but nottet.
You can also apply a wildcard to a single field, as in name:squir*. Put a label name that contains spaces inside quotes, as in "my label":squir*.
Leading wildcards are allowed, but a query that begins with * or ? is very slow and can time out before it returns results. Avoid starting a search query with either operator.
A ? at the end of a word is dropped when the word sits in a run of two or more plain search terms, on the assumption that it marks a question. So test? hello searches for the word test, while test? on its own stays a wildcard. A phrase or a field filter does not extend the run, so test? Country:France keeps the wildcard as well. A ? inside a word, as in te?t, is always a wildcard.
Example query |
Description |
|---|---|
|
Search documents that contain, for example, squirro and squirrel. |
|
Search documents that contain, for example, memonic and mnemonic. |
|
Search documents that contain, for example, test and text. |
|
Search documents that have a label named |
|
Search documents that do not have a label named |
|
Search documents whose |
Comparison Operators#
A comparison operator can replace the colon after a field name. It is meant for dates and numbers, including the numeric entity fields covered in the Entity Search section. Nothing stops you from using one on a text label, but the comparison is then alphabetical rather than numeric:
Operator |
Meaning |
|---|---|
|
Greater than |
|
Greater than or equal to |
|
Less than |
|
Less than or equal to |
Spaces around these operators are optional, so $_size > 100000 and $_size>100000 are equivalent.
= is not in that list, because on its own it is not a comparison operator. It is a second way to write the separator, so $item_language=en matches an exact value exactly as $item_language:en does. Unlike the operators above it takes no surrounding spaces: $_size = 100 is read as plain search terms rather than as a query on the field.
To bound a field on both sides, use the range syntax described in the Range Search section rather than combining two comparison operators with AND.
Field Search#
Field search restricts a query to one specific field, instead of searching the default title and body fields.
The $ prefix marks an item field, which is a field that every item carries, such as $title or $item_created_at. A field name written without the $ prefix is treated as a label instead, so $title:France and title:France do not search the same thing. For label search, see the Label Search section.
Both : and = separate a field name from its value, so $title:France and $title=France are equivalent.
Important
An item field name that does not exist is not rejected. The query runs and matches nothing, so a misspelled field name returns an empty result set rather than an error. Field names are also case sensitive, so $TITLE:France matches nothing while $title:France works. Watch for the reverse case as well: negating an unknown field, as in -$nosuchfield:x, excludes nothing and therefore matches every item. Check the spelling against the table below before concluding that a result set is right.
Note
Four names resolve to an item field even when written without the $ prefix: author, language, provider, and source. Write these ones without the prefix: author:"John Smith" searches the author name, whereas $author addresses a field that cannot be searched on its own. Those names are also reserved, so a label cannot take one of them as its name. For the full list of reserved names, see the Labels page.
Available Item Fields#
Field |
Matching |
Description |
|---|---|---|
|
Analyzed text |
Item title. |
|
Analyzed text |
Item body. |
|
Analyzed text |
Item summary. When the source does not supply one, it comes from the body. |
|
Analyzed text |
Summary that an AI tool writes for the item. Not every item has one. |
|
Exact value |
Squirro identifier of the item. |
|
Exact value |
Identifier that the item carried in its source system. |
|
Exact value |
Language of the item, as a two-letter ISO 639-1 code such as |
|
Date |
Date the item was created. This is the field that |
|
Date |
Date the item was last modified. |
|
URL |
Link to the item at its original location. Put the URL in quotes. A URL is held as one whole token, so |
|
Number |
Size of the stored item in bytes. See the Filtering by Item Size section. |
Analyzed text fields are language aware, so a query against one of them also matches stemmed forms and any configured synonyms. Fields matched by exact value accept only the value as stored, with no stemming, although a wildcard still works on them.
Note
Four item fields carry a different name in the query syntax than in the data loading and API item format. Query $item_id for the API field id, $item_language for language, $item_created_at for created_at, and $summary for abstract. For the API field names, see the Item Format page.
Example Field Queries#
Example query |
Description |
|---|---|
|
Search documents that have the term France in the title. |
|
Search documents that have the term France in the document body. |
|
Search for a specific document by id. |
|
Search documents created on or after February 15, 2023. |
|
Search documents created before February 1, 2015. |
|
Search documents created in the last 7 days.
|
|
Search documents larger than 100,000 bytes. See the Filtering by Item Size section. |
|
Search documents that link to a specific URL. The URL must be in quotes. |
|
Search documents written in a specific language. Use two-letter ISO 639-1 language codes, such as |
Filtering by Item Size#
$_size holds the size in bytes of the complete stored item, counting the title, body, summary, labels, and every other indexed field together. It is not the length of the body text on its own, and it is not the size of the original file that the item came from.
Use it with the comparison operators to find unusually large or small items:
$_size > 100000
$_size < 2000
$_size > 100000 AND $item_language:en
Label Search#
Use any document label to restrict the search. Label search is case sensitive, so the label name and its value both have to match the stored capitalization.
Example query |
Description |
|---|---|
|
Search documents that have a label named Country with a value France. |
|
Search documents that have a label named Country with a value United Kingdom. |
|
Search documents that have a label named Mixed Sentiment with a value Yes. Put a label name that contains spaces inside quotes. |
|
Search documents where Country is France or United Kingdom (multi-value search). |
The multi-value syntax field:[value1, value2, ...] matches documents where the field contains any of the values listed. It works on both labels and the analyzed text fields $title, $body, and $summary. On text fields the search still accounts for word variations, synonyms, and language-specific analysis, while on labels it matches the values as stored.
To bound a field between two values instead, see the Range Search section.
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.
Put quotes around any bound whose value contains a colon, such as a full timestamp. Without them the colon is read as a field separator and the range does not parse. Values without a colon, including plain dates and numbers, need no quotes.
Example query |
Description |
|---|---|
|
Find documents where |
|
Find documents where |
|
Mixed bounds: greater than or equal to 5, strictly less than 100. |
|
Find documents where |
|
Find documents where |
|
Find documents modified during 2024. |
|
Find documents modified between 09:00 and 17:00 on March 15, 2024. The times contain colons, so both bounds need quotes. |
Combine range queries with other operators as usual:
$modified_at:[2024-01-01 TO 2024-12-31] AND Country:France
On a field that holds several values per document, a bounded range is not the same as two comparison operators joined by AND. field:[a TO b] requires one single value to satisfy both bounds, whereas field > a AND field < b also matches when one value clears the lower bound and a different value falls under the upper one. Use the range syntax whenever the bounds have to apply to the same value.
Entity Search#
Entity search returns the items that contain a matching entity. Writing one takes the exact entity name, which you can look up on the Setup → Explore → Entities page, so in practice this is a tool for project creators rather than search users.
Wrap the criteria that an entity has to satisfy in the entity:{} literal. Everything inside one pair of braces has to be met by a single entity. Criteria split across two clauses may be met by the same entity or by different ones, so joining clauses with AND does not require two separate entities. Putting NOT in front of a clause excludes every item that has an entity matching it.
These entity fields can be queried:
Field |
Description |
|---|---|
|
Entity type, such as |
|
Entity name. Matched by exact value, so put a name containing spaces in quotes. |
|
How confident the extraction is. Values normally run from 0 to 1, but that range is a convention rather than a limit the platform enforces. |
|
How relevant the entity is to the item it appears on, on the same 0 to 1 convention as |
|
A custom property carried by the entity. |
|
A custom property holding a number. A |
|
Details of where the entity was found in the item, such as |
confidence, relevance, and any property holding a number accept the operators listed in the Comparison Operators section, as in properties.size > 100. A property holding text is matched by value instead, as in properties.region:US.
Only the fields above can be queried. The identifiers an entity carries in the API are not among them, so entity:{id:...} and entity:{external_id:...} are both accepted but match nothing.
Example query |
Description |
|---|---|
|
Items that contain a company entity named Thomson Reuters. |
|
Items that contain both of those company entities. Here the two names rule each other out, so the clauses cannot be met by the same entity. |
|
Items that contain a company entity extracted with more than 80% confidence. |
|
Items that contain a company entity whose confidence is not below 70%. That also matches an entity carrying no
confidence at all, so it is broader than |
|
Items that contain no company entity with a confidence of 20% or more. |
|
Items where a deal entity carries a relevance above 0.5 for that item. |
|
Items that contain a single deal entity matching both property values. |
|
Items that contain a deal entity whose numeric |
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.
You can prioritize individual elements of a query by boosting them. Sort by relevance to see the changed relevance scores.
Example query |
Description |
|---|---|
|
Search for France and Europe, but boost matches of France. |
|
Search for France in full text as well as in the Country label, and boost the items that carry the value in that label. |
|
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. The square brackets mark the optional parts and are not typed as part of the query:
sort:<field_name>[:<order>]
Where <order> is either asc for ascending or desc for descending. The order suffix is optional, and the default order is descending.
<field_name> is either a label name, an item field name written with the $ prefix, or one of the following sort keywords:
Keyword |
Sorts by |
|---|---|
|
Date the item was created. This is the default, and it sorts on |
|
Relevance score of the item. |
|
Item author. |
|
Item language. |
|
Item provider. |
|
Data source the item came from. |
sort:read and sort:starred are also accepted, but neither orders the results by your own read or bookmark state, and both return the same order. To narrow the results to items you have read or bookmarked, see the Bookmarked and Read Items section.
Additionally, you can add a second (or third etc) sorting criteria by adding
[;<2nd_sort_field>[:<2nd_order>]]
to the query syntax.
Example query |
Description |
|---|---|
|
Sort by date (descending order by default). |
|
Sort by date in ascending order. |
|
Sort by relevance in descending order. |
|
Sort by my_sortable_facet in descending order, and then by date in descending order. |
|
Sort query by date (default order is descending). |
Multiple Sorting Criteria#
You can sort on more than one criterion. The criteria apply in the order the query lists them: the first is the primary criterion, and each one after it breaks ties among the items the previous criteria rank equally.
Both of these queries sort by date in descending order, then by title in ascending order:
sort:date:desc;$title:asc
sort:date:desc sort:$title:asc
The first form lists the criteria inside one sort keyword, separated by a semicolon. The second repeats the sort keyword for each criterion. Both forms behave the same.
Important
Check the spelling of every label you sort on. A criterion that names a label the project does not have is not reported as an error: the query returns no results at all, whichever form you use. An unknown item field written with the $ prefix is ignored instead, and the other criteria still apply.
Time Increment#
You can control the time increments shown in the main timeline and in the dashboard widgets. To do so, add time_increment:<value> to a query.
A value is either a unit on its own, such as time_increment:day, or a number followed by a unit, such as time_increment:12hours. Eight units are available:
Unit |
Short form |
Example with a number |
|---|---|---|
|
none |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
none |
|
|
|
|
|
|
|
Each unit accepts its singular and plural spelling, so time_increment:day and time_increment:days are equivalent. Two units have no short form: month, because m already means minute, and second, where the single letter is not handled correctly. Write second or seconds in full.
Put only one time_increment clause in a query. When a query holds more than one, only one of them takes effect, and which one depends on how the query is written. That also applies when a query is assembled from several parts, such as a search query combined with dashboard filters, so set the increment in one of them only.
Choose an increment that keeps the number of buckets small. The finer the increment, the more buckets the results split into, and the slower both the query and the timeline become. Splitting a year of data into hourly increments, for example, is far more costly than splitting it into weekly ones.
Bookmarked and Read Items#
Bookmarked items are the items a user has added to their Bookmarks collection. The query syntax still names them with the legacy starred keyword, carried over from the previous starred system.
is:starred # Items in the user's Bookmarks collection
is:unstarred # Items not in the user's Bookmarks collection
is:starred reads the Bookmarks collection directly, so it works in any project. It matches nothing when the collection is empty.
is:unstarred reads the same collection, so it works everywhere too.
is:read and is:unread are also accepted, but they do not reflect which items you have read, so do not rely on their results. To find the items you have read, use the last_read scoring profile instead. By default it covers the 10 items you read most recently within the last 30 days, and count and last_days widen that, as in profile:{ last_read count:1000 last_days:365 }. It requires activity tracking. Without it, or when you have read nothing within last_days, the search returns no results. For more information, see the Scoring Profiles and Queries section.
Write these keywords in lower case and check them for typos. An unrecognized name such as is:STARRED is never reported as an error. Depending on the project configuration, it is either dropped from the query, so the search comes back unfiltered, or it matches nothing.
Scoring Profiles and Queries#
Accessing Scoring Profiles#
Scoring profiles use document metadata as additional filtering criteria to return the most relevant documents.
For an introduction to scoring profiles, see the How to Use Scoring Profiles to Customize Document Relevancy Scoring page.
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#
The plugins available out of the box include the following:
is_newMarks items as new when they were created after the last browsing session of the user. Requires activity tracking.
last_readBoosts the items the user read recently. The more recently the item was read, the higher the score. Requires activity tracking.
popular_itemBoosts popular items. The more popular the item is within the project, the higher the score.
conceptRuns concept search from within the search bar.
recommend_on_searchesRecommends items based on the search history of the user.
subscribed_communitiesAdds community filter queries for the communities the user subscribes to.
recency_boostMakes recent documents more relevant.
For more information about these plugins, see the Scoring Plugins page.
Example Queries#
The examples below show how to reference different scoring profiles in the search bar.
# 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 last browsing session of the user. 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 turned on 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 page.
# 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 restricts the results to items the current user has read, and scores the more recently read ones higher. The count parameter sets how many of the most recently read items are taken into account, and defaults to 10. The last_days parameter limits how far back to look, and defaults to 30 days.
This profile is useful for:
Finding items the user read previously.
Building reading history views.
Creating personalized dashboards based on user activity.
Read state is tracked per item, both when the item was read and how many times.
For detailed information about read and bookmarked items, see the Read, Unread, New, and Bookmarked Items page.
# 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 }
# Search for specific documents within the search history of the user, 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 the communities the user subscribes to, 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 when sorting by relevance (sort:relevance).
Besides ranking by profile, you can add extra scoring clauses with the rank_by:{} and scale_by:{} literals.
A document does not have to match these clauses to be retrieved. Documents that do match receive a boost to their relevance score.
A rank_by:{} clause adds the score of the wrapped query to the total score of each document, so its contribution is additive.
A scale_by:{} clause multiplies the total score of a matching document by the factor given after the closing brace, as in scale_by:{...}^2. Leaving the factor off applies 1.1, which raises the score by 10%. A rank_by:{} clause takes the same trailing factor.
These clauses always apply to the whole query, even when they sit inside a group.
So (wifi rank_by:{source:official}) OR (login rank_by:{source:unofficial}) returns documents matching wifi or login, and raises the score of those tagged official or unofficial in the source field.
Example query |
Description |
|---|---|
|
Search for the term |
|
Search for the term sequence |
|
Boost items that are tagged on sentence level with a classification output ( |
|
Search for the term |
You can also put a scoring profile inside a rank_by clause, for ranking specific to one use case such as a single dashboard or widget.
Example query |
Description |
|---|---|
|
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. |