Skip to content

UniqueQL Query Language

UniqueQL is an advanced query language designed to enhance search capabilities within the Unique AI platform. It enables powerful metadata filtering for vector search, full-text search, and combined search modes.

Overview

UniqueQL allows you to filter search results by metadata attributes such as: - File names and paths - URLs and document sources - Dates and timestamps - Custom metadata fields - Folder hierarchies - Document properties

The query language is versatile and can be translated into different query formats for various database systems, including PostgreSQL and Qdrant.

Importing UniqueQL

from unique_sdk import UQLOperator, UQLCombinator

Query Structure

A UniqueQL query consists of three components:

  1. Path: Specifies the metadata attribute to filter (e.g., ["title"], ["year"], ["folderIdPath"])
  2. Operator: Defines the type of comparison (e.g., EQUALS, CONTAINS, GREATER_THAN)
  3. Value: Provides the criteria for the filter

Operators

Comparison Operators

EQUALS - Exact match
1
2
3
4
5
{
    "path": ["year"],
    "operator": UQLOperator.EQUALS,
    "value": "2024"
}
NOT_EQUALS - Exclude value
1
2
3
4
5
{
    "path": ["status"],
    "operator": UQLOperator.NOT_EQUALS,
    "value": "archived"
}
CONTAINS - Substring match
1
2
3
4
5
{
    "path": ["title"],
    "operator": UQLOperator.CONTAINS,
    "value": "report"
}
NOT_CONTAINS - Exclude substring
1
2
3
4
5
{
    "path": ["title"],
    "operator": UQLOperator.NOT_CONTAINS,
    "value": "draft"
}

Numeric and Date Operators

These operators work with both numbers and dates (ISO 8601 format).

GREATER_THAN - Numeric comparison
1
2
3
4
5
{
    "path": ["size"],
    "operator": UQLOperator.GREATER_THAN,
    "value": 1000
}
GREATER_THAN - Date comparison
1
2
3
4
5
{
    "path": ["createdAt"],
    "operator": UQLOperator.GREATER_THAN,
    "value": "2024-01-01T00:00:00Z"
}
LESS_THAN_OR_EQUAL - Numeric range filtering
1
2
3
4
5
{
    "path": ["pageCount"],
    "operator": UQLOperator.LESS_THAN_OR_EQUAL,
    "value": 50
}
LESS_THAN - Date filtering
1
2
3
4
5
{
    "path": ["updatedAt"],
    "operator": UQLOperator.LESS_THAN,
    "value": "2024-12-31T23:59:59Z"
}

List Operators

IN - Match any value in list
1
2
3
4
5
{
    "path": ["department"],
    "operator": UQLOperator.IN,
    "value": ["Engineering", "Sales", "Marketing"]
}
NOT_IN - Exclude values
1
2
3
4
5
{
    "path": ["category"],
    "operator": UQLOperator.NOT_IN,
    "value": ["internal", "draft"]
}

Null/Empty Operators

IS_NOT_NULL - Exclude null values
1
2
3
4
5
{
    "path": ["author"],
    "operator": UQLOperator.IS_NOT_NULL,
    "value": None
}
IS_NOT_EMPTY - Exclude empty values
1
2
3
4
5
{
    "path": ["description"],
    "operator": UQLOperator.IS_NOT_EMPTY,
    "value": None
}

Combinators

Use AND and OR combinators to build complex queries:

AND - All conditions must match
{
    UQLCombinator.AND: [
        {
            "path": ["year"],
            "operator": UQLOperator.EQUALS,
            "value": "2024"
        },
        {
            "path": ["department"],
            "operator": UQLOperator.EQUALS,
            "value": "Engineering"
        }
    ]
}
OR - Any condition can match
{
    UQLCombinator.OR: [
        {
            "path": ["status"],
            "operator": UQLOperator.EQUALS,
            "value": "published"
        },
        {
            "path": ["status"],
            "operator": UQLOperator.EQUALS,
            "value": "reviewed"
        }
    ]
}

Complex Queries

Nested Queries - Filter nested metadata structures

Use NESTED operator for filtering within nested metadata structures:

from unique_sdk import UQLOperator, UQLCombinator

metadata_filter = {
    "path": ['diet', '*'],
    "operator": UQLOperator.NESTED,
    "value": {
        UQLCombinator.OR: [
            {
                UQLCombinator.OR: [
                    {
                        "path": ['food'],
                        "operator": UQLOperator.EQUALS,
                        "value": "meat",
                    },
                    {
                        "path": ['food'],
                        "operator": UQLOperator.EQUALS,
                        "value": "vegetables",
                    },
                ],
            },
            {
                "path": ['likes'],
                "operator": UQLOperator.EQUALS,
                "value": True,
            },
        ],
    },
}
Combining AND and OR - Complex filter logic
metadata_filter = {
    UQLCombinator.AND: [
        {
            "path": ["title"],
            "operator": UQLOperator.CONTAINS,
            "value": "report"
        },
        {
            UQLCombinator.OR: [
                {
                    "path": ["year"],
                    "operator": UQLOperator.EQUALS,
                    "value": "2024"
                },
                {
                    "path": ["year"],
                    "operator": UQLOperator.EQUALS,
                    "value": "2023"
                }
            ]
        }
    ]
}

Common Use Cases

Filter by Folder Path
metadata_filter = {
    "path": ["folderIdPath"],
    "operator": UQLOperator.CONTAINS,
    "value": "uniquepathid://scope_engineering_docs"
}

search = unique_sdk.Search.create(
    user_id=user_id,
    company_id=company_id,
    searchString="API documentation",
    searchType="COMBINED",
    metaDataFilter=metadata_filter
)
Filter by Date Range

Date operators work with ISO 8601 date strings. You can use dates with or without time:

# Date range filter
metadata_filter = {
    UQLCombinator.AND: [
        {
            "path": ["createdAt"],
            "operator": UQLOperator.GREATER_THAN_OR_EQUAL,
            "value": "2024-01-01"  # Date only
        },
        {
            "path": ["createdAt"],
            "operator": UQLOperator.LESS_THAN_OR_EQUAL,
            "value": "2024-12-31"  # Date only
        }
    ]
}

# Or with full timestamp
metadata_filter = {
    UQLCombinator.AND: [
        {
            "path": ["updatedAt"],
            "operator": UQLOperator.GREATER_THAN,
            "value": "2024-01-01T00:00:00Z"  # Full ISO 8601
        },
        {
            "path": ["updatedAt"],
            "operator": UQLOperator.LESS_THAN,
            "value": "2024-12-31T23:59:59Z"
        }
    ]
}
Filter by Multiple Departments
1
2
3
4
5
metadata_filter = {
    "path": ["department"],
    "operator": UQLOperator.IN,
    "value": ["Engineering", "Product", "Design"]
}
Exclude Specific Documents
metadata_filter = {
    UQLCombinator.AND: [
        {
            "path": ["status"],
            "operator": UQLOperator.EQUALS,
            "value": "published"
        },
        {
            "path": ["category"],
            "operator": UQLOperator.NOT_IN,
            "value": ["internal", "draft"]
        }
    ]
}

Using with Search API

Pass the metadata filter to the Search.create method
from unique_sdk import UQLOperator, UQLCombinator

# Build filter
metadata_filter = {
    UQLCombinator.AND: [
        {
            "path": ["year"],
            "operator": UQLOperator.EQUALS,
            "value": "2024"
        },
        {
            "path": ["department"],
            "operator": UQLOperator.CONTAINS,
            "value": "engineering"
        }
    ]
}

# Use in search
search_results = unique_sdk.Search.create(
    user_id=user_id,
    company_id=company_id,
    chatId=chat_id,
    searchString="project updates",
    searchType="COMBINED",
    metaDataFilter=metadata_filter,
    limit=30
)

Using with Content API

UniqueQL filters can also be used with the Content API
content_info_result = unique_sdk.Content.get_infos(
    user_id=user_id,
    company_id=company_id,
    metadataFilter={
        "or": [
            {
                "and": [
                    {
                        "operator": "contains",
                        "path": ["folderIdPath"],
                        "value": "uniquepathid://scope_abcdibgznc4bkdcx120zm5d"
                    },
                    {
                        "operator": "contains",
                        "path": ["title"],
                        "value": "ai"
                    }
                ]
            }
        ]
    },
    skip=0,
    take=3,
)

Best Practices

Combine Filters Efficiently

Use AND for restrictive filters and OR for inclusive filters
# Restrictive: Must match all
{
    UQLCombinator.AND: [
        {"path": ["year"], "operator": UQLOperator.EQUALS, "value": "2024"},
        {"path": ["status"], "operator": UQLOperator.EQUALS, "value": "published"}
    ]
}

# Inclusive: Match any
{
    UQLCombinator.OR: [
        {"path": ["department"], "operator": UQLOperator.EQUALS, "value": "Engineering"},
        {"path": ["department"], "operator": UQLOperator.EQUALS, "value": "Product"}
    ]
}

Test Filters Incrementally

Build complex filters step by step
# Start simple
filter1 = {
    "path": ["year"],
    "operator": UQLOperator.EQUALS,
    "value": "2024"
}

# Add more conditions
filter2 = {
    UQLCombinator.AND: [
        filter1,
        {
            "path": ["status"],
            "operator": UQLOperator.EQUALS,
            "value": "published"
        }
    ]
}

Complete Operator Reference

Operator Description Example Value Types
EQUALS Exact match String, Number, Boolean
NOT_EQUALS Exclude exact match String, Number, Boolean
CONTAINS Substring match String
NOT_CONTAINS Exclude substring String
GREATER_THAN Greater than Number, Date (ISO 8601)
GREATER_THAN_OR_EQUAL Greater than or equal Number, Date (ISO 8601)
LESS_THAN Less than Number, Date (ISO 8601)
LESS_THAN_OR_EQUAL Less than or equal Number, Date (ISO 8601)
IN Match any value in list Array
NOT_IN Exclude values in list Array
IS_NULL Value is null None
IS_NOT_NULL Value is not null None
IS_EMPTY Value is empty None
IS_NOT_EMPTY Value is not empty None
NESTED Filter nested structures Object

Next Steps

Now that you understand UniqueQL:

  1. Try Search with Filters - Use UniqueQL in search queries
  2. Explore Content API - Filter content with metadata
  3. See Tutorials - View rule-based search tutorial
  4. Read Full Documentation - Official UniqueQL documentation