2023:CMISQL Query: Difference between revisions

From Grooper Wiki
No edit summary
 
(22 intermediate revisions by the same user not shown)
Line 3: Line 3:
<blockquote>{{#lst:Glossary|CMIS Query}}</blockquote>
<blockquote>{{#lst:Glossary|CMIS Query}}</blockquote>


Also called a "CMISQL query", the querying language '''''CMIS Queries''''' use is based on a subset of the SQL-92 grammar. Where SQL is a querying language to search and select data in a database, "CMISQL" is a querying language to search and select documents (and their metadata properties) in a storage location, represented by a '''CMIS Repository''' in Grooper.
The querying language used by '''CMISQL Queries''' is based on a subset of the SQL-92 grammar. Where SQL is used to search and select data from a database, '''CMISQL''' is used to search and select documents (and their metadata properties) from a storage location, represented in Grooper by a '''CMIS Repository'''.
 
'''''Because the property used to configure a CMISQL Query is named "CMIS Query", "CMISQL Queries" are often referred to as "CMIS Queries".'''''


== About ==
== About ==
'''''CMIS Queries''''' use clauses to retrieve content from a '''CMIS Repositories''' based on certain metadata property values, much like a SQL query uses clauses to retrieve data from a database based on column values. In both cases, a <code>SELECT</code> clause is used to select content based on certain conditions determined by a <code>WHERE</code> clause  
'''CMIS Queries''' use clauses to retrieve content from a '''CMIS Repository''' based on metadata property values, much like a SQL query retrieves rows from a database based on column values. In both cases, a <code>SELECT</code> clause defines what is returned, and a <code>WHERE</code> clause defines the conditions used to filter results.


In general the CMISQL statement takes the following form:
In general, a CMISQL statement takes the following form:


  <span style="color:blue">'''SELECT'''</span> * <span style="color:blue">'''FROM'''</span> <Content Type>
  <span style="color:blue">'''SELECT'''</span> * <span style="color:blue">'''FROM'''</span> &lt;Content Type&gt;
  <span style="color:blue">'''WHERE'''</span> <Conditions>
  <span style="color:blue">'''WHERE'''</span> &lt;Conditions&gt;
  <span style="color:blue">'''ORDER BY'''</span> <Sort Criteria>
  <span style="color:blue">'''ORDER BY'''</span> &lt;Sort Criteria&gt;


 
For example, to retrieve all email messages in the Inbox of an Exchange CMIS Repository from a specific sender, ordered by the date received (oldest first), you could use the following query:
For example, if you wanted to retrieve all email messages in your Inbox folder over an Exchange '''CMIS Connection''' from a particular sender and order results by the date you received the email (oldest first), you could use the following query:


  <span style="color:blue">'''SELECT'''</span> * <span style="color:blue">'''FROM'''</span> Message
  <span style="color:blue">'''SELECT'''</span> * <span style="color:blue">'''FROM'''</span> Message
  <span style="color:blue">'''WHERE'''</span> (Sender '''LIKE''' '%user@example.com%' '''AND''' <span style="color:blue">IN_FOLDER</span>('/Inbox'))
  <span style="color:blue">'''WHERE'''</span> (Sender '''LIKE''' '%user@example.com%' '''AND''' <span style="color:blue">IN_FOLDER</span>('/Inbox'))
  <span style="color:blue">'''ORDER BY'''</span> DateTimeReceived <span style="color:blue">ASC</span>
  <span style="color:blue">'''ORDER BY'''</span> DateTimeReceived <span style="color:blue">ASC</span>


The sections below break down each clause in more detail.


Next, let's break down this query further and look at what each clause is doing.
=== Clause Information ===


=== Clause Information ===
==== SELECT ====
==== SELECT ====
'''SELECT *''' ''FROM Message''
Example CMISQL Query:
''WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox'))''
: <code>'''SELECT *''' FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC</code>
''ORDER BY DateTimeReceived ASC''


The <code>SELECT</code> clause defines a set of property values to be returned with each query result. "Property values" refers to the available metadata properties for the object type selected for the <code>From</code> statement.  For example, when querying email messages using in an Exchange '''CMIS Repository''', there are metadata properties for the sender, the subject line, the date the email was sent, and more.  All these metadata properties are part and parcel to the email message file itself.
The <code>SELECT</code> clause defines which metadata properties are returned with each query result. These properties depend on the content type specified in the <code>FROM</code> clause.


From a practical standpoint, your '''''CMIS Query''''' is ultimately returning ''documents''.  Files in a digital storage location.  You aren't retrieving individual metadata values, rather the whole file with all its various metadata included.  To that end you will use the <code>*</code> character to select ''all'' property values, when crafting a CMISQL query.
From a practical standpoint, CMIS Queries return '''documents''', not individual metadata values. Because the entire document (along with all metadata) is retrieved, CMIS Queries used for importing documents will always use <code>SELECT *</code>.


You will always start your '''''CMIS Query''''' with <code>SELECT *</code> when using a '''''CMIS Query''''' to import documents.
You will always begin an import-based CMIS Query with <code>SELECT *</code>.


{|class="fyi-box"
{|class="fyi-box"
Line 40: Line 40:
'''FYI'''
'''FYI'''
|
|
When would you use something besides <code>SELECT *</code>?  When would you construct a CMISQL query, such as <code>SELECT Property_A, Property_B, Property_C</code> and so on?
When would you use something other than <code>SELECT *</code>?


The answer is '''''CMIS Lookups'''''. A '''''CMIS Lookup''''' operates much like a database lookup.  Instead of querying a database table's columns for data, a '''''CMIS Query''''' queries the metadata properties of documents in a storage location.
This occurs when using '''CMIS Lookups'''. A CMIS Lookup functions similarly to a database lookup, querying metadata values rather than retrieving documents.
* Technically, a '''''CMIS Query''''' is used in that case as well.  However, '''''CMIS Queries''''' are much more commonly used to retrieve documents from a storage location upon import, which is the focus of this article.
 
* For more information on '''''CMIS Lookups''''' please visit the [[CMIS Lookup]] article.
* CMIS Queries used for importing content are the primary focus of this article.
* For more information, see the [[CMIS Lookup]] article.
|}
|}


==== FROM ====
==== FROM ====
''SELECT *'' '''FROM Message'''
Example CMISQL Query:
''WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox'))''
: <code>SELECT * '''FROM Message''' WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC</code>
''ORDER BY DateTimeReceived ASC''


The <code>FROM</code> clause determines what type of '''content''' you're searching for, such as a digital file or a folder and their metadata properties.
The <code>FROM</code> clause determines the '''content type''' being queried, such as documents or folders.
* The type of content you select determines what metadata properties you have access to when building the conditional logic in your query's <code>WHERE</code> clause.


Depending on the '''CMIS Connection''' type, you will have different options to select from.  Some have simple "Document" and "Folder" content types, representing documents and folders respectively.  Some have a multitude of content types, each with metadata properties specific to the '''CMIS Binding'''.
* The selected content type determines which metadata properties are available for use in the <code>WHERE</code> clause.
* For example, the '''''Exchange''''' binding's '''Message''' content type has property values relating to email messages, such as '''''Subject''''', '''''Sender''''' and '''''DateTimeSent'''''.
* For example, The '''''SharePoint''''' binding's content types can be Document Libraries, giving you access to custom metadata properties you've created on the SharePoint site by adding custom columns to the Document Library.


In our example, we wanted to query email messages in an '''''Exchange''''' repository. So, we selected the '''Message''' type by adding <code>FROM Message</code> to our query.
Available content types depend on the '''CMIS Repository''' and its '''CMIS Binding''' (connection type).
 
* Example: The '''Exchange''' binding exposes a ''Message'' content type with properties such as ''Subject'', ''Sender'', and ''DateTimeSent''.
* Example: The '''SharePoint''' binding exposes document library content types, including custom metadata columns.
 
In this example, the query targets Exchange email messages by specifying <code>FROM Message</code>.


==== WHERE ====
==== WHERE ====
''SELECT * FROM Message''
Example CMISQL Query:
'''WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox'))'''
: <code>SELECT * FROM Message '''WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox'))''' ORDER BY DateTimeReceived ASC</code>
''ORDER BY DateTimeReceived ASC''


The <code>WHERE</code> clause defines what search conditions must be met for a document to be retrieved.  Each condition is defined by a "predicate".  You can use any metadata available to the content type (as determined by the <code>FROM</code> clause) in your query conditions. 
The <code>WHERE</code> clause defines the conditions that must be met for a document to be returned.
* Multiple conditions/predicates can be joined with the <code>AND</code> or <code>OR</code> operators.
* You can manipulate the logical order of operations by using nested parenthesis.
* You can logically negate predicates using the <code>NOT</code> operator.


===== Search Predicates =====
* Conditions are defined using '''predicates'''.
The following is a list of predicates:
* Multiple predicates can be combined using <code>AND</code> or <code>OR</code>.
* Parentheses control logical precedence.
* Predicates can be negated using the <code>NOT</code> operator.


===== Where Predicates =====
A '''Where Predicate''' represents a logical condition applied to a CMISQL query’s <code>WHERE</code> clause.
{|cellspacing="5" cellpadding="10"
{|cellspacing="5" cellpadding="10"
|'''Predicate'''||'''Description'''||'''Example'''
|'''Predicate'''||'''Description'''||'''Example'''
Line 79: Line 81:
|'''''Comparison Predicate'''''
|'''''Comparison Predicate'''''
|
|
Specifies a condition for an individual property using comparisons, such as "equals to" <code>=</code> or "less than" <code><</code> or "greater than" <code>></code>.
Specifies search criteria by comparing a property value using operators, such as <code>=</code>, <code>&lt;</code>, <code>&gt;</code>, <code>LIKE</code>, or <code>IS</code>.
* The <code>LIKE</code> and <code>IS</code> operators are also available for certain properties.
*<li class="attn-bullet> Operator support varies by property and CMIS Binding.
*: Example: The Exchange binding's "Subject" property cannot use the <code>=</code> operator. The <code>LIKE</code> predicate must be used instead.
|<code>DateTimeCreated < '12/31/2007'</code>
|<code>DateTimeCreated < '12/31/2007'</code>
|-style="background-color:#ddf5f5"
|-style="background-color:#ddf5f5"
|'''''In Predicate'''''||Specifies a list of allowed values for a property.  This list is separated by commas. When using the CMIS Query Editor, hit the Enter key after each entry. The comma separated list will appear in the query.||<code>FileExtension IN ('.pdf', '.docx', '.xlsx')</code>
|'''''IN Predicate'''''
|Specifies search criteria for an individual property, using a list of allowed values.
|<code>FileExtension IN ('.pdf', '.docx', '.xlsx')</code>
|-style="background-color:#ddf5f5"
|-style="background-color:#ddf5f5"
|'''''Contains Predicate'''''
|'''''CONTIAINS Predicate'''''
|Specifies a full-text query.
|Performs a full-text search.
* You can use <code>AND</code>, <code>OR</code> and <code>NOT</code> operators when crafting search parameters.
* You can use <code>AND</code>, <code>OR</code> and <code>NOT</code> operators when crafting search parameters.
* Please note only external platforms that support full text searching are compatible with with the '''''Contains Predicate'''''.
*<li class="attn-bullet"> Note: Only platforms that support full text searching are compatible with with the Contains Predicate.
|<code>CONTAINS('mortgage AND payment AND NOT vehicle')</code>
|<code>CONTAINS('mortgage AND payment AND NOT vehicle')</code>
|-style="background-color:#ddf5f5"
|-style="background-color:#ddf5f5"
|'''''Scope Predicate'''''||Restricts the search scope to a specific folder (<code>IN_FOLDER</code>) or a specific folder including its subfolders(<code>IN_TREE</code>)||<code>IN_FOLDER('/Documents/Grooper')</code>
|'''''MATCHES Predicate'''''
|Defines filtering criteria for a string property, where the property value must match a regular expression.
|<code>cmis:name MATCHES '^[A-Z]{3}-\d{4}$'</code>
|-style="background-color:#ddf5f5"
|'''''Scope Predicate'''''
|
Restricts the search scope to the direct children (<code>IN_FOLDER</code>) or all descendants  (<code>IN_TREE</code>) of a specific folder.
*<li class="attn-bullet"> Note: The <code>NOT</code> operator cannot be used with the Scope Predicate.
|<code>IN_FOLDER('/Documents/Grooper')</code>
|-style="background-color:#ddf5f5"
|'''''AT_LEVEL Predicate'''''
|Matches documents/folders at a specific level below the base folder.
|<code>AT_LEVEL(2)</code>
|-style="background-color:#ddf5f5"
|-style="background-color:#ddf5f5"
|'''''Predicate List'''''||Defines a collection of predicates to be evaluated as a group using a logical operator (<code>AND</code> or <code>OR</code>).  Allows multiple search conditions in a single CMISQL query.||<code>(Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox/'))</code>
|'''''Predicate List'''''||Groups multiple predicates using <code>AND</code> or <code>OR</code>.  Allows multiple search conditions in a single CMISQL query.||<code>(Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox/'))</code>
|}
|}
* Note: Not every property type may be able to utilize every predicate/operators within a predicate. For example, the '''''Subject''''' property on the '''''Exchange''''' binding cannot use the <code>=</code> operator when crafting a '''''Comparison Predicate'''''.
*<li class="attn-bullet"> Note: Predicate support varies by CMIS Binding.
* Note: The <code>NOT</code> operator cannot be used with the <code>IN_FOLDER</code> or <code>IN_TREE</code> '''''Scope Predicate'''''.
** Example: The [[SharePoint]] binding does not support the Scope Predicate's <code>IN_FOLDER</code> option. <code>IN_TREE</code> must be used instead.
** Example: The [[NTFS]] binding will not support the <code>CONTAINS()</code> predicate unless Windows Search indexing is enabled.


In our example, we used a '''''Predicate List''''' that collected two predicates: the '''''Comparison Predicate''''' and '''''Scope Predicate'''''.  This queried email messages from certain sender (<code>Sender LIKE '%user@example.com%'</code>) and in our inbox folder (<code>IN_FOLDER('/Inbox/')</code>) Since we wanted to filter content by multiple criteria, the two conditions were joined with the <code>AND</code> operator.
 
 
In the example query<code>WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox'))</code>, a '''Predicate List''' combines:
* A '''Comparison Predicate''' (Sender)
* A '''Scope Predicate''' (Inbox folder)


==== ORDER BY ====
==== ORDER BY ====
''SELECT *'' ''FROM Message''
Example CMISQL Query:
''WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox'))''
: <code>SELECT * FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) '''ORDER BY DateTimeReceived ASC'''</code>
'''ORDER BY DateTimeReceived ASC'''</code>


The <code>ORDER BY</code> clause is an optional clause which allows you to specify the order in which results are returned.  You can sort by multiple properties using a comma separated list.  Each property name may be followed by <code>ASC</code> or <code>DESC</code> to indicate ascending or descending sort direction.
* The default sort direction is ascending.  However, it is still considered best practice to include the <code>ASC</code> tag to properties you wish to sort in ascending order.


In our example, we wanted to sort our incoming messages by oldest received first.
The optional <code>ORDER BY</code> clause defines the sort order of query results.
 
* Multiple properties may be specified using a comma-separated list.
* <code>ASC</code> (ascending) and <code>DESC</code> (descending) are supported.
* Ascending order is the default, but explicitly specifying it is recommended.


== CMISQL Query Editor ==
== CMISQL Query Editor ==
If you are not familiar with the CMISQL syntax (or even SQL), you may find it easier to use the '''''CMIS Query Editor''''', instead of writing the full query yourself.  This allows you to configure the CMISQL query using a series of property grids and menu selections instead of writing out the query from scratch.
If you are unfamiliar with CMISQL syntax, the '''CMIS Query Editor''' allows you to build queries using a property grid rather than writing them manually.


The '''''CMIS Query Editor''''' is accessible in two locations:
The editor is available in:
# When configuring the '''''Import Query Results''''' Import Provider's '''''CMIS Query''''' property.
# The '''Import Query Results''' provider
# Using a '''CMIS Repository's''' "Search Repository" tab.
# A '''CMIS Repository''' via the "Search" tab


{|class="attn-box"
{|class="attn-box"
Line 121: Line 144:
&#9888;
&#9888;
|
|
Only certain external storage platforms are currently queryable with a '''''CMIS Query'''''.  The following '''''CMIS Binding''''' sources '''''cannot''''' be queried currently.
The following CMIS Bindings cannot be queried using CMISQL:
* '''FTP'''
* '''SFTP'''
* '''NTFS''' (unless indexed by Windows Search)


* '''''FTP'''''
These bindings are not compatible with the '''Import Query Results''' provider.
* '''''SFTP'''''
|}
* '''''NTFS''''' (If the folder path is not indexed by the Windows Search service and/or Windows Search is not running on the storage server)


As such, these bindings are '''''not''''' suitable for the '''''Import Query Results''''' provider (You should instead use '''''Import Descendants''''').  Furthermore, you will not have access to the "Search Repository" tab for these bindings when selecting a '''CMIS Repository'''.
<br>
Again, the exception to this is '''''NTFS'''''. If the folder path IS indexed in Windows and the Windows Search service IS running, then you CAN use the "Search Repository" tab and '''''CMIS Queries'''''.
|}


=== How to Access the CMIS Query Editor ===
=== How to Access the CMIS Query Editor ===
<tabs style="margin:20px">
<tab name="Option 1: Import Query Results - CMIS Query" style="margin:20px">


=== Option 1: Import Query Results > CMIS Query ===
There are two locations where the '''CMIS Query Editor''' can be accessed:
Most commonly, you will use a CMISQL query to import documents using the '''''Import Query Results''''' provider.
* From the '''Import Query Results''' provider when editing its ''CMIS Query''. This allows users to filter imported documents based on the results of a CMISQL query.
* From a '''CMIS Repository's''' "Search" tab. This allows users to test CMISQL queries independently of the Import Query Results provider.
 
''Note:''' How to use the CMIS Query Editor is demonstrated in the [[#How to Use the CMIS Query Editor|next section]].
==== Import Query Results > CMIS Query ====
Most commonly, you will use a CMISQL query to import documents using the '''Import Query Results''' provider.


{|class="fyi-box"
{| class="fyi-box"
|
|  
'''FYI'''
'''FYI'''
|
|
The '''''Import Query Results''''' provider is one of two '''''Import Providers''''' that use a '''CMIS Connection''' to bring document content into Grooper. If you need more information on '''''Import Query Results''''', please visit the [[CMIS Import]] article.
The '''Import Query Results''' provider is one of two Import Providers that use a '''CMIS Connection''' to bring document content into Grooper. For more information, see the [[CMIS Import]] article.
|}
|}


{|cellpadding=10 cellspacing=5
{| cellpadding=10 cellspacing=5
|valign=top style="width:40%"|
| valign=top style="width:40%" |
<br>
<br>
# When configuring the import settings, you will first select which '''CMIS Repository''' you want to query by selecting one using the '''''Repository''''' property.
# When configuring the import settings, select the '''CMIS Repository''' to query using the ''Repository'' property.
# Then, select the '''''CMIS Query''''' property.
# Select the ''CMIS Query'' property.
#* Note: Some '''CMIS Bindings''' are ''not'' CMISQL queryable (For example, the '''''FTP''''' and '''''SFTP''''' CMIS Bindings). If the '''CMIS Repository''' is not queryable, you will ''not'' see this '''''CMIS Query''''' property.
#* '''Note:''' Some CMIS Bindings are ''not'' CMISQL queryable (for example, ''FTP'' and ''SFTP''). If the CMIS Repository is not queryable, the ''CMIS Query'' property will not be available.
# Press the ellipsis button at the end of the property to bring up the '''''CMIS Query Editor'''''.
# Click the ellipsis button at the end of the property to open the CMIS Query Editor.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_01.png]]
[[File:2023_CMIS-Query_02_How-To_01.png]]
|-
|-
|valign=top|
| valign=top |
<br>
<br>
This is the '''''CMIS Query Editor'''''. Using this interface you can craft a CMISQL query in one of two ways:
This is the '''CMIS Query Editor'''. Using this interface, you can craft a CMISQL query in one of two ways:
 
# Use the property grid to configure the clauses of the query.
# You can use this property grid to configure the various clauses of the query statement.
# Free-type the query directly in the text editor.
# You can free-type the query in this text editor.
| valign=top |
 
 
We will demonstrate how to use this query editor in the [[#How to Use the CMIS Query Editor|next section]]
|valign=top|
[[File:2023_CMIS-Query_02_How-To_02.png]]
[[File:2023_CMIS-Query_02_How-To_02.png]]
|}
|}
</tab>
<tab name="Option 2: The Search Repository Tab" style="margin:20px">


=== Option 2: The Search Repository Tab ===
'''Note:''' How to use the CMIS Query Editor is demonstrated in the [[#How to Use the CMIS Query Editor|next section]].
You can also use the '''''CMIS Query Editor''''' when searching for documents in a '''CMIS Repository''' using the "Search Repository" tab.
 
==== CMIS Repository > Search Tab ====
You can also access the '''CMIS Query Editor''' when searching for documents in a '''CMIS Repository''' using the "Search" tab.


{|cellpadding=10 cellspacing=5
{| cellpadding=10 cellspacing=5
|valign=top style="width:40%"|
| valign=top style="width:40%" |
<br>
<br>
# Select the '''CMIS Repository''' you want to query in the Node Tree.
# Select the '''CMIS Repository''' in the Node Tree.
# Navigate to the "Search Repository" tab.
# Navigate to the "Search" tab.
#* Note: Some '''CMIS Bindings''' are ''not'' CMISQL queryable (For example, the '''''FTP''''' and '''''SFTP''''' CMIS Bindings). If the '''CMIS Repository''' is not queryable, you will ''not'' see this "Search Repository" tab.
#* '''Note:''' Some '''CMIS Bindings''' are ''not'' CMISQL queryable (for example, ''FTP'' and ''SFTP''). If the CMIS Repository is not queryable, the "Search" tab will not be available.
# You can use this property grid to configure the various clauses of the query statement.
# Use the property grid to configure the clauses of the query.
# You can free-type the query in this text editor.
# Free-type the query directly in the text editor.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_03.png]]
[[File:2023_CMIS-Query_02_How-To_03.png]]
|}
|}


''Note:''' How to use the CMIS Query Editor is demonstrated in the [[#How to Use the CMIS Query Editor|next section]].


We will demonstrate how to use this query editor in the [[#How to Use the CMIS Query Editor|next section]]
== How to Use the CMIS Query Editor ==
</tab>
Next, we will demonstrate how to use the '''CMIS Query Editor''' to filter email messages based on specific criteria. The CMIS Query Editor interface allows you to construct a CMISQL query using metadata exposed by the selected CMIS Binding.
</tabs>


=== How to Use the CMIS Query Editor ===
In this example, we will use the '''Exchange''' binding, which exposes queryable metadata for email messages such as subject, sender, and received date. Our query will import email messages that meet the following conditions:
Next, we're going to illustrate how to use the '''''CMIS Query Editor''''' in order to filter email messages based on certain criteria. The '''''CMIS Query Editor's''''' interface allows you to configure the CMISQL query based on available metadata to the '''''CMIS Binding'''''.
# Only email messages are imported (excluding other Exchange content such as appointments or tasks).
# Only messages located in a specific folder are imported.
# Only messages containing specific text search terms are imported.
# Only messages from a specific sender are imported.
# Only unread messages are imported.


We will use the '''''Exchange''''' binding, which has a selection of queryable metadata for email messages, such as the email's subject and date the message was received.  Our query will import email messages based on the following conditions:
This walkthrough covers the fundamentals of building a CMISQL query using the CMIS Query Editor.
# Only messages are to be imported (as opposed to other '''''Exchange''''' content, such as appointments or tasks).
# Only messages in a certain folder will be imported.
# Only messages containing specific text search terms will be imported.
# Only messages from a certain sender will be imported.
# Only messages that have not been read yet will be imported.


This will get us through the basics of building a CMISQL query using the '''''CMIS Query Editor'''''.
<tabs style="margin:20px">


<tabs style="margin:20px">
<tab name="The SELECT and FROM Clauses" style="margin:20px">
<tab name="The SELECT and FROM Clauses" style="margin:20px">
{|cellpadding=10 cellspacing=5
{| cellpadding=10 cellspacing=5
|valign=top style="width:40%"|
| valign=top style="width:40%" |
=== The SELECT and FROM Clauses ===
=== The SELECT and FROM Clauses ===
The property grid is divided into the various clauses that form the CMISQL query. Adjusting these properties will adjust the CMISQL query.
The property grid is divided into sections that correspond to the clauses of the CMISQL query. Adjusting these properties automatically updates the query text.


# The '''''Select''''' property will adjust the <code>SELECT</code> clause.
# The '''Select''' property controls the <code>SELECT</code> clause.
#* By default this property is set to ''*''.
#* By default, this property is set to <code>*</code>.
#* This forms the start of the query <code>SELECT *</code>
#* This produces the opening of the query: <code>SELECT *</code>.
# The '''''From''''' property will adjust the <code>FROM</code> clause.
# The '''From''' property controls the <code>FROM</code> clause.
#* Each '''''CMIS Binding''''' will default to a different content type. Generally, the default content type corresponds to a "document" in the storage location.
#* Each CMIS Binding defaults to a specific content type.
#* The '''''Exchange''''' binding's default is ''Item''.  However, we actually want to change this.  An "item" is too generic.  It refers to message files, appointment files, task files, and note files in an Exchange inbox.
#* For the Exchange binding, the default content type is ''Item''.
#** We want to import email messages, and define our query conditions to filter out emails using metadata specifically accessible to those types of files. We need to use the ''Message'' content type to do this properly.
#* An ''Item'' is a generic Exchange object and may represent messages, appointments, tasks, or notes.
|valign=top|
#* To query email-specific metadata, we must change the content type to ''Message''.
| valign=top |
[[File:2023_CMIS-Query_02_How-To_04.png]]
[[File:2023_CMIS-Query_02_How-To_04.png]]
|-
|-
|valign=top|
| valign=top |
=== Changing Content Types in the FROM Clause ===
=== Changing Content Types in the FROM Clause ===
From this point forward, we will continue using the property grid to edit the query.


We will use the '''''CMIS Query Editor's''''' property panel to edit our query going forward.
# Select the '''From''' property.
 
# Use the dropdown list to select ''Message''.
# Since we want to adjust the content type in our <code>FROM</code> clause, we will select the '''''From''''' property.
#* This restricts the query to email messages and exposes message-specific metadata.
# Using the dropdown menu, we've selected ''Message''.
# The CMISQL query text is updated automatically.
#* This will query specifically message files over our Exchange connection, and give use access to their metadata for our querying conditions.
#* <code>SELECT * FROM Item</code> becomes <code>SELECT * FROM Message</code>.
# This automatically updates the full text of our CMISQL query.
#* <code>SELECT * FROM Item</code> changed to <code>SELECT * FROM Message</code>
 
 


As we use the property grid to further configure our query, the query's text will update automatically.
As additional properties are configured, the query text will continue to update automatically.
* This gives you a method of editing the CMISQL query without free-typing the query.
* This allows you to build a CMISQL query without manually typing it.
* However, you certainly can type out the full query text if you prefer ''not'' to use the property grid to enter the CMISQL query.
* You may also freely edit the query text directly if preferred.
** You can also go back and forth between the property grid and the text editor.
** You can switch back and forth between the property grid and the text editor at any time.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_05.png]]
[[File:2023_CMIS-Query_02_How-To_05.png]]
|}
|}
</tab>
</tab>
<tab name="The WHERE Clause" style="margin:20px">
<tab name="The WHERE Clause" style="margin:20px">
{|cellpadding=10 cellspacing=5
{| cellpadding=10 cellspacing=5
|valign=top style="width:40%"|
| valign=top style="width:40%" |
=== The WHERE Clause ===
=== The WHERE Clause ===
Next, we will configure the '''Where''' property to define the filter conditions for our query.


Next, we will use the '''''Where''''' property to configure the various filter conditions we've set for ourselves.
# Select the '''Where''' property.
 
# Choose the desired predicate type from the dropdown list.
# Select the '''''Where''''' property.
#* When filtering on multiple criteria, always select ''Predicate Collection''.
# Using the dropdown list, select the search predicate you wish to use.
#* In this example, we will use both ''Comparison Predicates'' and a ''Scope Predicate''.
#* If you are filtering based of multiple criteria. you will '''''ALWAYS''''' choose ''Predicate Collection''.
| valign=top |
#* We need to filter based on the values of multiple metadata properties, ''and'' we need to use both a '''''Comparison Predicate''''' and a '''''Scope Predicate'''''.  So, we have selected '''''Predicate Collection'''''.
|valign=top|
[[File:2023_CMIS-Query_02_How-To_06.png]]
[[File:2023_CMIS-Query_02_How-To_06.png]]
|-
|-
|valign=top|
| valign=top |
=== Using Predicate Collection for Multiple Search Conditions ===
=== Using Predicate Collection for Multiple Conditions ===
# Expand the '''''Where''''' sub-properties to add your query criteria.
# Expand the '''Where''' sub-properties.
# The default '''''Logical Operator''''' is ''AND''.
# The default '''Logical Operator''' is ''AND''.
#* This is appropriate for our situation, as we want to use the ''AND'' operator.  ALL conditions must be met in our case.
#* This is appropriate here, as all conditions must be met.
#* But be aware you also have access to the ''OR'' operator. Using this operator will look for any number of the defined predicates. So if at least one of the predicates is present in the document, it will be returned as a result.  
#* The ''OR'' operator is also available and returns results that match any predicate.
# Next, we will add our various query conditions using the '''''Expressions''''' property.
# Use the '''Expressions''' property to add predicates.
# Press the ellipsis button at the end to bring up the '''''Where Predicate Expressions''''' collection editor.
# Click the ellipsis button to open the '''Where Predicate Expressions''' editor.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_07.png]]
[[File:2023_CMIS-Query_02_How-To_07.png]]
|}
|}
</tab>
</tab>
<tab name="Adding Search Predicates" style="margin:20px">
<tab name="Adding Search Predicates" style="margin:20px">
{|cellpadding=10 cellspacing=5
{| cellpadding=10 cellspacing=5
|valign=top style="width:40%"|
| valign=top style="width:40%" |
=== Adding Search Predicates ===
=== Adding Search Predicates ===
Now that we're in the '''''Where Predicate Expressions''''' collection editor, we can start adding and configuring our search conditions.
The Where Predicate Expressions editor is used to define individual search conditions.


# Press the ''Add'' button to add a predicate to the list.
# Click ''Add'' to create a new predicate.
# We will start by adding a '''''Scope Predicate''''' to restrict the search scope to a specific folder.
# Begin by adding a '''Scope Predicate''' to limit the query to a specific folder.
|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_08.png]]
[[File:2023_CMIS-Query_02_How-To_08.png]]
|-
|-
|valign=top|
| valign=top |
=== The Scope Predicate ===
=== The Scope Predicate ===
The '''Scope Predicate''' restricts the query to a specific folder.


The '''''Scope Predicate''''' allows you to choose a folder from which you want to retrieve documents.
# Select the '''Search Scope''' property and click the ellipsis button.
# Choose a folder from the CMIS Repository’s folder hierarchy.
# In this example, the scope is restricted to the ''Wiki'' folder.
# Click ''OK'' to confirm.


# Select the '''''Search Scope''''' property and press the ellipsis button at the end.
{| class="fyi-box"
# This will bring up a folder browser, representing your connected '''CMIS Repository's''' hierarchical folder structure.
| '''FYI'''
# We're going to restrict our scope to this subfolder named "Wiki" in the connected email account.
# Press ''OK'' to finalize your selection.
 
{|class="fyi-box"
|
|
'''FYI'''
If '''Include Subfolders''' is ''False'', the <code>IN_FOLDER()</code> predicate is used, limiting results to the selected folder only.
|
If '''''Include Subfolders''''' is ''False'', the <code>IN_FOLDER()</code> predicate will be used.
:&bull; This will restrict the query's search to the single selected folder in the folder hierarchy.


If '''''Include Subfolders''''' is ''True'', the <code>IN_TREE()</code> predicate will be used.
If '''Include Subfolders''' is ''True'', the <code>IN_TREE()</code> predicate is used, including the selected folder and all subfolders.
:&bull; This will restrict the query's search to the selected folder ''and'' search any of its subfolders in the folder hierarchy.
|}
|}
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_09.png]]
[[File:2023_CMIS-Query_02_How-To_09.png]]
|-
|-
|valign=top|
| valign=top |
=== The Contains Predicate ===
=== The Contains Predicate ===
If the connected CMIS Repository supports full-text search, you can use the '''Contains Predicate''' to search for specific text.


If the storage location your '''CMIS Repository''' is connected to supports full text searching, you can use the '''''Contains Predicate''''' to query documents based on specific text search terms.
In this example, we will retrieve email messages containing the phrase ''Wiki Vitals''.


For example, we want to retrieve email messages pertaining to "Wiki Vitals", a specific kind of report generated nightly about the Grooper wiki and sent to my email.
To add a '''Contains Predicate''':
 
# Press the ''Add'' button and select '''Contains Predicate'''
To add a '''''Contains Predicate''''':
# This adds a new Contains Predicate to our list of predicates
# Press the ''Add'' button and select '''''Contains Predicate'''''
# Using the '''Search String''' property, enter the text you would like to search for.
# This adds a new '''''Contains Predicate''''' to our list of predicates
# Using the '''''Search String''''' property, enter the text you would like to search for.
#* In our case, only messages with the text ''Wiki Vitals'' somewhere in the subject line or email body or otherwise in the message's metadata will be retrieved.
#* In our case, only messages with the text ''Wiki Vitals'' somewhere in the subject line or email body or otherwise in the message's metadata will be retrieved.
#* Notice Grooper automatically generates the property syntax for the query, <code>CONTAINS('Wiki AND Vitals')</code>.
#* Notice Grooper automatically generates the property syntax for the query, <code>CONTAINS('Wiki AND Vitals')</code>.


{|class="attn-box"
{| class="attn-box"
|
| &#9888;
&#9888;
|
|
Please note only external platforms that support full text searching are compatible with with the '''''Contains Predicate.
Only platforms that support full-text searching can use the Contains Predicate.
|}
|}
|valgin=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_10.png]]
[[File:2023_CMIS-Query_02_How-To_10.png]]
|-
|-
|valgin=top|
| valign=top |
=== The NOT Operator ===
=== The NOT Operator ===
Any predicate can be logically negated using the <code>NOT</code> operator.


All predicates can be logically negated using the <code>NOT</code> operator.  For example, most of these "Wiki Vitals" reports are daily reports. These are the emails I want to process.  However, once a month, there is a monthly report.  I DO NOT want to process those documents.
In this example, monthly reports should be excluded. These emails contain the phrase ''Monthly Report''.
 
The only way I know it's a monthly report is the term "monthly report" is listed in the body of the email.  I can use the '''''Contains Predicate''''' and the <code>NOT</code> operator to exempt these monthly reports from the query.


To logically negate a predicate:
To logically negate a predicate:
# Add the predicate using the ''Add'' button.
# Add the predicate using the ''Add'' button.
# We've added another '''''Contains Predicate'''''.
# We've added another '''Contains Predicate'''.
# Configure the predicate's search parameters.
# Configure the predicate's search parameters.
#* What do we ''not'' want to retrieve in this case?  Messages with the text ''Monthly Report'' somewhere in their body.  So, we've configured the '''''Search String''''' property to search for that term.
#* What do we ''not'' want to retrieve in this case?  Messages with the text ''Monthly Report'' somewhere in their body.  So, we've configured the '''Search String''' property to search for that term.
# Change the '''''Not''''' property to ''True''.
# Change the '''Not''' property to ''True''.
#* This will negate the predicate's logic.  If the email contains the search term, it will ''not'' be retrieved.
#* This will negate the predicate's logic.  If the email contains the search term, it will ''not'' be retrieved.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_11.png]]
[[File:2023_CMIS-Query_02_How-To_11.png]]
|-
|-
|valign=top|
| valign=top |
=== The Comparison Predicate ===
=== The Comparison Predicate ===
The '''Comparison Predicate''' filters documents using metadata values and comparison operators such as <code>=</code>, <code>&gt;</code>, or <code>&lt;</code>.


The '''''Comparison Predicate''''' specifies search criteria based on a document's metadata property values, using comparison operators such as <code>></code>, <</code> or <code>=</code>.
In this example, we will only import unread messages.
 
For example, we will use a '''''Comparison Predicate''''' to only import emails that have not been read yet, whose "IsRead" property value equals "False".


To add a '''''Comparison Predicate'''':
# Press the ''Add'' button and select '''Comparison Predicate'''
# Press the ''Add'' button and select '''''Comparison Predicate'''''
# This adds a new Comparison Predicate to our list of predicates
# This adds a new '''''Comparison Predicate''''' to our list of predicates
# Using the '''Property Name''' property, select a property from a list of the documents' available metadata properties.
# Using the '''''Property Name''''' property, select a property from a list of the documents' available metadata properties.
#* What metadata properties are available will be determined by the '''CMIS Repository's''' binding/connection type and the content type selected in the <code>FROM</code> clause.
#* What metadata properties are available will be determined by the '''CMIS Repository's''' binding/connection type and the content type selected in the <code>FROM</code> clause.
#* We've selected the ''IsRead'' property.
#* We've selected the ''IsRead'' property.
# Using the '''''Comparison Operator''''' select which operator you want to use for comparison.
# Using the '''Comparison Operator''' select which operator you want to use for comparison.
#* Depending on the value's type (string, decimal, Boolean, etc.) different comparison operators may be available.
#* Depending on the value's type (string, decimal, Boolean, etc.) different comparison operators may be available.
#* Here, we are checking for equivalency using the <code>=</code> operator.
#* Here, we are checking for equivalency using the <code>=</code> operator.
# Using the '''''Search Value''''' property, enter the control variable you want to use for comparision.
# Using the '''Search Value''' property, enter the control variable you want to use for comparison.
#* In our case, we want to check if these emails have not been read, indicated by the email message's "IsRead" property being ''False''.
#* In our case, we want to check if these emails have not been read, indicated by the email message's "IsRead" property being ''False''.
|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_12.png]]
[[File:2023_CMIS-Query_02_How-To_12.png]]
|-
|-
|valign=top|
| valign=top |
=== The LIKE Operator ===
==== Example: Searching by "Sender" using the LIKE operator ====
 
The <code>LIKE</code> operator is used to match substrings in string values.
The <code>LIKE</code> operator is used to match substrings of string values.  In many cases, it must be used instead of the <code>=</code> when you're comparing string variables.
 
For example, if we want to use a '''''Comparison Predicate''''' to filter messages based on the "Sender" (a string value), we will need to use the <code>LIKE</code> variable to do so.  Furthermore, we will also need to encase the search term in the <code>%</code> wildcard symbol.


# Here, we've added a new '''''Comparison Predicate''''' to only retrieve messages sent by a specific email address.
To filter by sender:
# We've slected ''Sender'' for the '''''Property Name'''''
# Add a '''Comparison Predicate'''.
# This property must use the <code>LIKE</code> '''''Comparison Operator'''''.
# Select ''Sender'' as the '''Property Name'''.
# For the '''''Search Value''''' property we've entered ''%cdearner@bisok.com%''.
# Choose <code>LIKE</code> as the operator.
#* Effectively, we just enter the email address we want to search for (cdearner@bisok.com) with percent sign wildcards at the front and end.
# Enter <code>%cdearner@bisok.com%</code> as the search value.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_13.png]]
[[File:2023_CMIS-Query_02_How-To_13.png]]
|-
|-
|colspan=2|
| colspan=2 |
{|class="fyi-box"
{| class="fyi-box"
| '''FYI'''
|
|
'''FYI'''
The <code>LIKE</code> operator matches substrings using wildcards:
|
* <code>%</code> matches zero or more characters.
The <code>LIKE</code> operator specifies that a property value must contain a substring. It takes the general form <code>PropertyName LIKE 'Expression'</code>, where <code>PropertyName</code> is the query name of a string property, and <code>Expression</code> is a string literal using the <code>%</code> and <code>_</code> characters as wildcards. The <code>LIKE</code> operator is not case sensitive.
* <code>_</code> matches exactly one character.
:&bull; The <code>%</code> wildcard substitutes for zero or more characters.  
* A <code>LIKE</code> expression without wildcards behaves like <code>=</code>.
:&bull; The <code>_</code> wildcard substitutes for exactly one character.  
 
:&bull; A <code>LIKE</code> expression with no wildcards is equivalent to using the <code>=</code> operator.  
Examples:
:&bull; For example, the expression <code>'grooper%'</code> will match cases where the property value begins with "grooper", while <code>'%grooper'</code> will match cases where the property value ends with "grooper". The expression <code>'grooper%review'</code> will match cases where the property value begins with "grooper" and ends with "review".
* "dog_" matches "dog" and "dogs"
* "%dog" matches "dog" and "catdog"


Some '''CMIS Bindings''' have limited support for <code>LIKE</code> expressions, and will raise errors when unsupported features are used. Examples of such issues are as follows:
Some CMIS Bindings have limited <code>LIKE</code> support and may restrict wildcard usage.
:&bull; Some bindings '''only''' support the <code>%</code> wildcard at the beginning and end of the expression (i.e. <code>'%grooper%'</code>).
:&bull; Some bindings '''do not''' support the "ends with" form of <code>LIKE</code> (i.e. <code>'%grooper'</code>).
:&bull; Some bindings '''do not''' support the <code>_</code> wildcard at all.
|}
|}
|-
|-
|valign=top|
| valign=top |
=== Finish Adding Predicates ===
=== Finish Adding Predicates ===
 
# Click ''OK'' to close the predicate editor.
# When you have finished adding predicates to the collection list, press the ''OK'' button.
| valign=top |
|valign=top|
[[File:2023_CMIS-Query_02_How-To_14.png]]
[[File:2023_CMIS-Query_02_How-To_14.png]]
|-
|-
|valign=top|
| valign=top |
<br>
# When complete, the predicates form the conditions of the query’s <code>WHERE</code> clause.
#<li value=2> When finished, the search predicates will form the conditional parameters of the query's <code>WHERE</code> clause.
| valign=top |
|valign=top|
[[File:2023_CMIS-Query_02_How-To_15.png]]
[[File:2023_CMIS-Query_02_How-To_15.png]]
|}
|}
</tab>


We ''could'' be done at this point.  We have the three basic parts of a '''''CMIS Query'''''.
<tab name="The ORDER BY Clause and Testing the Query" style="margin:20px">
{| cellpadding=10 cellspacing=5
| valign=top style="width:40%" |
=== The ORDER BY Clause ===
The optional <code>ORDER BY</code> clause controls the sort order of the query results.


# The query starts with <code>SELECT *</code>
In this example, we will sort messages by sent date, with the most recent messages listed first.
# The <code>FROM</code> clause determines which content (documents/folders and their metadata properties) we're querying from the '''CMIS Repository'''/storage location.
# The <code>WHERE</code> clause defines the query's search conditions.


Optionally, you may want to ''order'' the documents Grooper retrieves.  We will do that next, with the <code>ORDER BY</code> clause.
# Select the '''Order By''' property and click the ellipsis button.
</tab>
| valign=top |
<tab name="The ORDER BY Clause (and Testing the Query)" style=margin:20px">
=== The ORDER BY Clause ===
The <code>ORDER BY</code> clause is an optional CMISQL querying clause used to change the sort order of the documents Grooper retrieves.  You can sort by any metadata property available.
 
For example, we may want to sort by the date the email message was sent.  And specifically we want the most recent email first in the list and the last email last in the list.  We're going to need an <code>ORDER BY</code> clause to do this.
{|cellpadding=10 cellspacing=5
|valign=top style="width:40%"|
<br>
To add an <code>ORDER BY</code> clause:
# Select the '''''Order By''''' property, and press the ellipsis button at the end.
|valign=top|
[[File:2023_CMIS-Query_02_How-To_16.png]]
[[File:2023_CMIS-Query_02_How-To_16.png]]
|-
|-
|valign=top|
| valign=top |
# <li value=2>This brings up the '''''Order By''''' collection editor.</li>
# Click ''Add'' to add a sort field.
# Press ''Add'' to add a new sort element.
# Using the '''Property Name'''' property, select which document metadata property you want to sort by.
# Using the '''''Property Name'''''' property, select which document metadata property you want to sort by.
#* Example: Select ''DateTimeSent'' as the '''Property Name'''.
#* In our case, we've chosen the email messages ''DateTimeSent'' property, storing what date and time the email was sent.
# Using the '''Sort Direction''' property, select which direction you want to sort by.
# Using the '''''Sort Direction''''' property, select which direction you want to sort by.
#* Choose ''ASC'' to sort in ascending order.
#* Choose ''ASC'' to sort in ascending order.
#* Choose ''DESC'' to sort in descending order.
#* Choose ''DESC'' to sort in descending order.
|valign=top|
| valign=top |
[[File:2023_CMIS-Query_02_How-To_17.png]]
[[File:2023_CMIS-Query_02_How-To_17.png]]
|-
|-
|valign=top|
| valign=top |
=== Testing the Query ===
=== Testing the Query ===
 
# The completed query is validated automatically.
# With this <code>ORDER BY</code> clause added, our query is now complete.
# Click ''Execute Query'' to test it.
# This message indicates the query is valid.  There is nothing wrong with our syntax.
# Results appear in the '''Query Results''' panel.
# You can test the query by pressing the ''Execute Query'' button.
# Double-click a result to view it in the '''Document Preview''' panel.
# The query's results will appear in the '''''Query Results''''' pannel
| valign=top |
# If you double-click on an item in the list, it will appear in the '''''Document Preview''''' panel.
|valign=top|
[[File:2023_CMIS-Query_02_How-To_18.png]]
[[File:2023_CMIS-Query_02_How-To_18.png]]
|}
|}
</tab>
</tab>
</tabs>
</tabs>


Line 457: Line 450:


=== NTFS ===
=== NTFS ===
{{#lst:2023:NTFS (CMIS Connection Type)|ntfs_query_limitations}}
{{#lst:NTFS (CMIS Binding)|ntfs_query_limitations}}
=== SharePoint ===
=== SharePoint ===
{{#lst:2023:SharePoint (CMIS Connection Type)|sharepoint_query_limitations}}
{{#lst:SharePoint (CMIS Binding)|sharepoint_query_limitations}}
=== Box ===
=== Box ===
{{#lst:2023:Box (CMIS Connection Type)|box_query_limitations}}
{{#lst:Box (CMIS Binding)|box_query_limitations}}
=== Exchange ===
=== Exchange ===
{{#lst:2023:Exchange (CMIS Connection Type)|exchange_query_limitations}}
{{#lst:Exchange (CMIS Binding)|exchange_query_limitations}}
=== IMAP ===
{{#lst:IMAP (CMIS Binding)|imap_query_limitations}}
 
== Object Model info ==
 
Type name: '''{{TypeName|CMISQL Query}}'''
 
{{Inheritance|Grooper Object|Connected Object|Embedded Object|CMISQL Element|CMISQL Query}}
 
<big>Derived Types</big>
 
CMISQL Query is the Grooper object that selects documents or folders from a CMIS Repository.
* CMISQL Query has no derived types.
* However, several sibling types are key to its composition and use in Grooper.
 
:::: {{WikiHelpLinks|CMISQL Element}}
::::: '''CMISQL Query''' (''{{HelpLink|CMISQL Query}}'')
::::: {{WikiHelpLinks|Join Clause}} - Used to create the JOIN clause of a CMISQL Query
::::: {{WikiHelpLinks|ORDER BY Element}} - Used to create the ORDER BY clause of a CMISQL Query
::::: {{WikiHelpLinks|Select Element}} - Used to create the SELECT clause of a CMISQL Query
::::: {{WikiHelpLinks|Where Predicate}} - Used to create the WHERE clause of a CMISQL Query. Its derived types expose search conditions that can be added to the WHERE clause.
:::::: {{WikiHelpLinks|AT_LEVEL Predicate}} - Matches documents/folders at a specific level below the base folder.
:::::: {{WikiHelpLinks|Comparison Predicate}} - Specifies search criteria for an individual property using a comparison operator (=, <, >, LIKE etc)
:::::: {{WikiHelpLinks|CONTAINS Predicate}} - Specifies full-text search criteria
:::::: {{WikiHelpLinks|IN Predicate}} - Specifies search criteria for an individual property, using a list of allowed values.
:::::: {{WikiHelpLinks|MATCHES Predicate}} - Specifies filtering criteria for a string property, where the property value must match a regular expression.
:::::: {{WikiHelpLinks|Predicate List}} - Defines a collection of search conditions separated by logical AND/OR operators.
:::::: {{WikiHelpLinks|Scope Predicate}} - Restricts the search scope to the direct children (IN_FOLDER) or all descendants (IN_TREE) of a folder.

Latest revision as of 10:13, 5 February 2026

This article is about an older version of Grooper.

Information may be out of date and UI elements may have changed.

202520232021

A CMISQL Query (aka CMIS Query) is Grooper's way of searching for documents in CMIS Repositories. Commonly, CMISQL Queries are used by Import Query Results to import documents from a CMIS Repository. CMISQL Queries are also used by CMIS Lookup to lookup data from a CMIS Repository. CMISQL Queries are based on a subset of the SQL-92 syntax for querying databases, with some specialized extensions added to support querying CMIS sources.

  • CMISQL Queries are configured using the "CMIS Query" property found in "Import Query Results" and "CMIS Lookup".

The querying language used by CMISQL Queries is based on a subset of the SQL-92 grammar. Where SQL is used to search and select data from a database, CMISQL is used to search and select documents (and their metadata properties) from a storage location, represented in Grooper by a CMIS Repository.

Because the property used to configure a CMISQL Query is named "CMIS Query", "CMISQL Queries" are often referred to as "CMIS Queries".

About

CMIS Queries use clauses to retrieve content from a CMIS Repository based on metadata property values, much like a SQL query retrieves rows from a database based on column values. In both cases, a SELECT clause defines what is returned, and a WHERE clause defines the conditions used to filter results.

In general, a CMISQL statement takes the following form:

SELECT * FROM <Content Type> WHERE <Conditions> ORDER BY <Sort Criteria>

For example, to retrieve all email messages in the Inbox of an Exchange CMIS Repository from a specific sender, ordered by the date received (oldest first), you could use the following query:

SELECT * FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC

The sections below break down each clause in more detail.

Clause Information

SELECT

Example CMISQL Query:

SELECT * FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC

The SELECT clause defines which metadata properties are returned with each query result. These properties depend on the content type specified in the FROM clause.

From a practical standpoint, CMIS Queries return documents, not individual metadata values. Because the entire document (along with all metadata) is retrieved, CMIS Queries used for importing documents will always use SELECT *.

You will always begin an import-based CMIS Query with SELECT *.

FYI

When would you use something other than SELECT *?

This occurs when using CMIS Lookups. A CMIS Lookup functions similarly to a database lookup, querying metadata values rather than retrieving documents.

  • CMIS Queries used for importing content are the primary focus of this article.
  • For more information, see the CMIS Lookup article.

FROM

Example CMISQL Query:

SELECT * FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC

The FROM clause determines the content type being queried, such as documents or folders.

  • The selected content type determines which metadata properties are available for use in the WHERE clause.

Available content types depend on the CMIS Repository and its CMIS Binding (connection type).

  • Example: The Exchange binding exposes a Message content type with properties such as Subject, Sender, and DateTimeSent.
  • Example: The SharePoint binding exposes document library content types, including custom metadata columns.

In this example, the query targets Exchange email messages by specifying FROM Message.

WHERE

Example CMISQL Query:

SELECT * FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC

The WHERE clause defines the conditions that must be met for a document to be returned.

  • Conditions are defined using predicates.
  • Multiple predicates can be combined using AND or OR.
  • Parentheses control logical precedence.
  • Predicates can be negated using the NOT operator.
Where Predicates

A Where Predicate represents a logical condition applied to a CMISQL query’s WHERE clause.

Predicate Description Example
Comparison Predicate

Specifies search criteria by comparing a property value using operators, such as =, <, >, LIKE, or IS.

  • Operator support varies by property and CMIS Binding.
    Example: The Exchange binding's "Subject" property cannot use the = operator. The LIKE predicate must be used instead.
DateTimeCreated < '12/31/2007'
IN Predicate Specifies search criteria for an individual property, using a list of allowed values. FileExtension IN ('.pdf', '.docx', '.xlsx')
CONTIAINS Predicate Performs a full-text search.
  • You can use AND, OR and NOT operators when crafting search parameters.
  • Note: Only platforms that support full text searching are compatible with with the Contains Predicate.
CONTAINS('mortgage AND payment AND NOT vehicle')
MATCHES Predicate Defines filtering criteria for a string property, where the property value must match a regular expression. cmis:name MATCHES '^[A-Z]{3}-\d{4}$'
Scope Predicate

Restricts the search scope to the direct children (IN_FOLDER) or all descendants (IN_TREE) of a specific folder.

  • Note: The NOT operator cannot be used with the Scope Predicate.
IN_FOLDER('/Documents/Grooper')
AT_LEVEL Predicate Matches documents/folders at a specific level below the base folder. AT_LEVEL(2)
Predicate List Groups multiple predicates using AND or OR. Allows multiple search conditions in a single CMISQL query. (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox/'))
  • Note: Predicate support varies by CMIS Binding.
    • Example: The SharePoint binding does not support the Scope Predicate's IN_FOLDER option. IN_TREE must be used instead.
    • Example: The NTFS binding will not support the CONTAINS() predicate unless Windows Search indexing is enabled.


In the example queryWHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')), a Predicate List combines:

  • A Comparison Predicate (Sender)
  • A Scope Predicate (Inbox folder)

ORDER BY

Example CMISQL Query:

SELECT * FROM Message WHERE (Sender LIKE '%user@example.com%' AND IN_FOLDER('/Inbox')) ORDER BY DateTimeReceived ASC


The optional ORDER BY clause defines the sort order of query results.

  • Multiple properties may be specified using a comma-separated list.
  • ASC (ascending) and DESC (descending) are supported.
  • Ascending order is the default, but explicitly specifying it is recommended.

CMISQL Query Editor

If you are unfamiliar with CMISQL syntax, the CMIS Query Editor allows you to build queries using a property grid rather than writing them manually.

The editor is available in:

  1. The Import Query Results provider
  2. A CMIS Repository via the "Search" tab

The following CMIS Bindings cannot be queried using CMISQL:

  • FTP
  • SFTP
  • NTFS (unless indexed by Windows Search)

These bindings are not compatible with the Import Query Results provider.


How to Access the CMIS Query Editor

There are two locations where the CMIS Query Editor can be accessed:

  • From the Import Query Results provider when editing its CMIS Query. This allows users to filter imported documents based on the results of a CMISQL query.
  • From a CMIS Repository's "Search" tab. This allows users to test CMISQL queries independently of the Import Query Results provider.

Note:' How to use the CMIS Query Editor is demonstrated in the next section.

Import Query Results > CMIS Query

Most commonly, you will use a CMISQL query to import documents using the Import Query Results provider.

FYI

The Import Query Results provider is one of two Import Providers that use a CMIS Connection to bring document content into Grooper. For more information, see the CMIS Import article.


  1. When configuring the import settings, select the CMIS Repository to query using the Repository property.
  2. Select the CMIS Query property.
    • Note: Some CMIS Bindings are not CMISQL queryable (for example, FTP and SFTP). If the CMIS Repository is not queryable, the CMIS Query property will not be available.
  3. Click the ellipsis button at the end of the property to open the CMIS Query Editor.


This is the CMIS Query Editor. Using this interface, you can craft a CMISQL query in one of two ways:

  1. Use the property grid to configure the clauses of the query.
  2. Free-type the query directly in the text editor.

Note: How to use the CMIS Query Editor is demonstrated in the next section.

CMIS Repository > Search Tab

You can also access the CMIS Query Editor when searching for documents in a CMIS Repository using the "Search" tab.


  1. Select the CMIS Repository in the Node Tree.
  2. Navigate to the "Search" tab.
    • Note: Some CMIS Bindings are not CMISQL queryable (for example, FTP and SFTP). If the CMIS Repository is not queryable, the "Search" tab will not be available.
  3. Use the property grid to configure the clauses of the query.
  4. Free-type the query directly in the text editor.

Note:' How to use the CMIS Query Editor is demonstrated in the next section.

How to Use the CMIS Query Editor

Next, we will demonstrate how to use the CMIS Query Editor to filter email messages based on specific criteria. The CMIS Query Editor interface allows you to construct a CMISQL query using metadata exposed by the selected CMIS Binding.

In this example, we will use the Exchange binding, which exposes queryable metadata for email messages such as subject, sender, and received date. Our query will import email messages that meet the following conditions:

  1. Only email messages are imported (excluding other Exchange content such as appointments or tasks).
  2. Only messages located in a specific folder are imported.
  3. Only messages containing specific text search terms are imported.
  4. Only messages from a specific sender are imported.
  5. Only unread messages are imported.

This walkthrough covers the fundamentals of building a CMISQL query using the CMIS Query Editor.

The SELECT and FROM Clauses

The property grid is divided into sections that correspond to the clauses of the CMISQL query. Adjusting these properties automatically updates the query text.

  1. The Select property controls the SELECT clause.
    • By default, this property is set to *.
    • This produces the opening of the query: SELECT *.
  2. The From property controls the FROM clause.
    • Each CMIS Binding defaults to a specific content type.
    • For the Exchange binding, the default content type is Item.
    • An Item is a generic Exchange object and may represent messages, appointments, tasks, or notes.
    • To query email-specific metadata, we must change the content type to Message.

Changing Content Types in the FROM Clause

From this point forward, we will continue using the property grid to edit the query.

  1. Select the From property.
  2. Use the dropdown list to select Message.
    • This restricts the query to email messages and exposes message-specific metadata.
  3. The CMISQL query text is updated automatically.
    • SELECT * FROM Item becomes SELECT * FROM Message.

As additional properties are configured, the query text will continue to update automatically.

  • This allows you to build a CMISQL query without manually typing it.
  • You may also freely edit the query text directly if preferred.
    • You can switch back and forth between the property grid and the text editor at any time.

The WHERE Clause

Next, we will configure the Where property to define the filter conditions for our query.

  1. Select the Where property.
  2. Choose the desired predicate type from the dropdown list.
    • When filtering on multiple criteria, always select Predicate Collection.
    • In this example, we will use both Comparison Predicates and a Scope Predicate.

Using Predicate Collection for Multiple Conditions

  1. Expand the Where sub-properties.
  2. The default Logical Operator is AND.
    • This is appropriate here, as all conditions must be met.
    • The OR operator is also available and returns results that match any predicate.
  3. Use the Expressions property to add predicates.
  4. Click the ellipsis button to open the Where Predicate Expressions editor.

Adding Search Predicates

The Where Predicate Expressions editor is used to define individual search conditions.

  1. Click Add to create a new predicate.
  2. Begin by adding a Scope Predicate to limit the query to a specific folder.

The Scope Predicate

The Scope Predicate restricts the query to a specific folder.

  1. Select the Search Scope property and click the ellipsis button.
  2. Choose a folder from the CMIS Repository’s folder hierarchy.
  3. In this example, the scope is restricted to the Wiki folder.
  4. Click OK to confirm.
FYI

If Include Subfolders is False, the IN_FOLDER() predicate is used, limiting results to the selected folder only.

If Include Subfolders is True, the IN_TREE() predicate is used, including the selected folder and all subfolders.

The Contains Predicate

If the connected CMIS Repository supports full-text search, you can use the Contains Predicate to search for specific text.

In this example, we will retrieve email messages containing the phrase Wiki Vitals.

To add a Contains Predicate:

  1. Press the Add button and select Contains Predicate
  2. This adds a new Contains Predicate to our list of predicates
  3. Using the Search String property, enter the text you would like to search for.
    • In our case, only messages with the text Wiki Vitals somewhere in the subject line or email body or otherwise in the message's metadata will be retrieved.
    • Notice Grooper automatically generates the property syntax for the query, CONTAINS('Wiki AND Vitals').

Only platforms that support full-text searching can use the Contains Predicate.

The NOT Operator

Any predicate can be logically negated using the NOT operator.

In this example, monthly reports should be excluded. These emails contain the phrase Monthly Report.


To logically negate a predicate:

  1. Add the predicate using the Add button.
  2. We've added another Contains Predicate.
  3. Configure the predicate's search parameters.
    • What do we not want to retrieve in this case? Messages with the text Monthly Report somewhere in their body. So, we've configured the Search String property to search for that term.
  4. Change the Not property to True.
    • This will negate the predicate's logic. If the email contains the search term, it will not be retrieved.

The Comparison Predicate

The Comparison Predicate filters documents using metadata values and comparison operators such as =, >, or <.

In this example, we will only import unread messages.

  1. Press the Add button and select Comparison Predicate
  2. This adds a new Comparison Predicate to our list of predicates
  3. Using the Property Name property, select a property from a list of the documents' available metadata properties.
    • What metadata properties are available will be determined by the CMIS Repository's binding/connection type and the content type selected in the FROM clause.
    • We've selected the IsRead property.
  4. Using the Comparison Operator select which operator you want to use for comparison.
    • Depending on the value's type (string, decimal, Boolean, etc.) different comparison operators may be available.
    • Here, we are checking for equivalency using the = operator.
  5. Using the Search Value property, enter the control variable you want to use for comparison.
    • In our case, we want to check if these emails have not been read, indicated by the email message's "IsRead" property being False.

Example: Searching by "Sender" using the LIKE operator

The LIKE operator is used to match substrings in string values.

To filter by sender:

  1. Add a Comparison Predicate.
  2. Select Sender as the Property Name.
  3. Choose LIKE as the operator.
  4. Enter %cdearner@bisok.com% as the search value.

FYI

The LIKE operator matches substrings using wildcards:

  • % matches zero or more characters.
  • _ matches exactly one character.
  • A LIKE expression without wildcards behaves like =.

Examples:

  • "dog_" matches "dog" and "dogs"
  • "%dog" matches "dog" and "catdog"

Some CMIS Bindings have limited LIKE support and may restrict wildcard usage.

Finish Adding Predicates

  1. Click OK to close the predicate editor.

  1. When complete, the predicates form the conditions of the query’s WHERE clause.

The ORDER BY Clause

The optional ORDER BY clause controls the sort order of the query results.

In this example, we will sort messages by sent date, with the most recent messages listed first.

  1. Select the Order By property and click the ellipsis button.

  1. Click Add to add a sort field.
  2. Using the Property Name' property, select which document metadata property you want to sort by.
    • Example: Select DateTimeSent as the Property Name.
  3. Using the Sort Direction property, select which direction you want to sort by.
    • Choose ASC to sort in ascending order.
    • Choose DESC to sort in descending order.

Testing the Query

  1. The completed query is validated automatically.
  2. Click Execute Query to test it.
  3. Results appear in the Query Results panel.
  4. Double-click a result to view it in the Document Preview panel.

Unsupported query configurations

NTFS

The NTFS connection binding will not support the CONTAINS() predicate (for full text searching) unless the Windows file system has been indexed by the Windows Search service.

SharePoint

The SharePoint connection binding does not support the IN_FOLDER predicate.

  • You must use the IN_TREE predicate instead when selecting a folder location to query.
  • Be aware the IN_TREE search is recursive where IN_FOLDER is not. This means any subfolders will be queried as well as the targeted folder.


The SharePoint connection binding has a hard limitation when it comes to querying larger repositories, with many thousands of folders and files.

  • There is currently a threshold limit of 5000 rows.
  • This means if a query has to scan more than 5000 items to return an item, SharePoint will return the following error:
    • "Internal Server Error (500): The attempted operation is prohibited because it exceeds the list view threshold."

Box

Search values are required for Box CMISQL Queries. You must include a WHERE clause with at least one valid search condition.


The Box API has some built in requirements to perform search queries. This is not something Grooper can get around. In the past, this has caused Grooper users a lot of confusion when configuring WHERE clauses in CMISQL search queries.

To avoid confusion the following properties are not queryable at this time:
  • Created by (cmis:createdBy)
  • Modified by (cmis:lastModifiedBy)


The Box binding does not support does not support the IN_FOLDER predicate.

  • You must use the IN_TREE predicate instead when selecting a folder location to query.
  • Be aware the IN_TREE search is recursive where IN_FOLDER is not. This means any subfolders will be queried as well as the targeted folder.


Box has some documented limitations in its CMIS implementation in general. In most cases, Grooper is able to circumvent these issues, but not in all cases. Grooper is only able to return what Box gives us when executing a CMISQL query.

  • Documents are not immediately queryable after their metadata templates have been edited in Box. If you have just added/edited fields in a Box document's metadata template, there is some lag time between when Grooper can query that data. You may need to wait several hours before a CMISQL query will return the document.
  • We have encountered sporadic issues when using aliases (i.e. SELECT propertyName AS 'AliasName') in a Box CMIS Lookup query. As such, CMIS Lookups used to populate Grooper fields may be unreliable. However, please continue to report this issue to the support team at support@bisok.com. Additional reports will help the QA team diagnose this issue and help the Development team implement a solution, if possible.

Exchange

When configuring a WHERE clause (using a Comparison Predicate), the "Subject", "Sender", "To Recipients", "Cc Recipients", and "Bcc Recipients" cannot use the = operator.

  • Use the LIKE operator instead.
    • Incorrect syntax: Sender = '%user@example.com%'
    • Correct syntax: Sender LIKE '%user@example.com%'
  • BE AWARE: EWS only supports substring matching for these properties. You must use the % wildcard on either side of the search term when using the LIKE operator.
    • Incorrect syntax: Sender LIKE 'user@example.com'
    • Correct syntax: Sender LIKE '%user@example.com%'

IMAP

Gmail and other email clients does not support the IN_FOLDER or IN_TREE predicates because these are not part of the standard IMAP protocol.

  • Instead Gmail uses "labels" which are not searchable by Grooper's querying mechanism.
  • Some email clients do support these search predicates. We do not have a complete list of providers that do and do not support IN_FOLDER and IN_TREE at this time.


Object Model info

Type name: Grooper.CMIS.CmisQuery

Inheritance

Grooper Object (Grooper.GrooperObject)
Connected Object (Grooper.ConnectedObject)
Embedded Object (Grooper.EmbeddedObject)
CMISQL Element (Grooper.CMIS.QueryElement)
CMISQL Query (Grooper.CMIS.CmisQuery)

Derived Types

CMISQL Query is the Grooper object that selects documents or folders from a CMIS Repository.

  • CMISQL Query has no derived types.
  • However, several sibling types are key to its composition and use in Grooper.
CMISQL Element (Grooper.CMIS.QueryElement)
CMISQL Query (Grooper.CMIS.CmisQuery)
Join Clause (Grooper.CMIS.JoinClause) - Used to create the JOIN clause of a CMISQL Query
ORDER BY Element (Grooper.CMIS.OrderByElement) - Used to create the ORDER BY clause of a CMISQL Query
Select Element (Grooper.CMIS.SelectElement) - Used to create the SELECT clause of a CMISQL Query
Where Predicate (Grooper.CMIS.WherePredicate) - Used to create the WHERE clause of a CMISQL Query. Its derived types expose search conditions that can be added to the WHERE clause.
AT_LEVEL Predicate (Grooper.CMIS.AtLevelPredicate) - Matches documents/folders at a specific level below the base folder.
Comparison Predicate (Grooper.CMIS.ComparisonPredicate) - Specifies search criteria for an individual property using a comparison operator (=, <, >, LIKE etc)
CONTAINS Predicate (Grooper.CMIS.ContainsPredicate) - Specifies full-text search criteria
IN Predicate (Grooper.CMIS.InPredicate) - Specifies search criteria for an individual property, using a list of allowed values.
MATCHES Predicate (Grooper.CMIS.MatchesPredicate) - Specifies filtering criteria for a string property, where the property value must match a regular expression.
Predicate List (Grooper.CMIS.PredicateCollection) - Defines a collection of search conditions separated by logical AND/OR operators.
Scope Predicate (Grooper.CMIS.ScopePredicate) - Restricts the search scope to the direct children (IN_FOLDER) or all descendants (IN_TREE) of a folder.