Community Edition | Enterprise Edition

Developer Reference

State Table

The following table provides a detailed breakdown of each step in the federation process, along with the corresponding status and other key state information.

Action Module Status Notes
Search object created views.py SearchViewSet.create() Search.status:
NEW_SEARCH
UPDATE_SEARCH
Required:
Search.query_string
Pre-processing search.py search() Search.status:
PRE_PROCESSING
Checks permissions
Loads the Search object
Pre-query processing search.py search() Search.status:
PRE_QUERY_PROCESSING
Processes Search.query_string and updates Search.query_string_processed
Federation search.py search() Search.status:
FEDERATING
PARTIAL_RESULTS
FULL_RESULTS
Creates one Connector for each SearchProvider in the Search
Connector Init connectors/connector.py
connectors/db_connector.py
Connector.status:
INIT
READY
Loads the Search and SearchProvider
Connector Federate federate() Connector.status:
FEDERATING
Connector Query Processing process_query() Connector.status:
FEDERATING
Processes Search.query_string_processed and stores it in Connector.query_string_to_provider
Connector Construct Query construct_query() Connector.status:
FEDERATING
Takes Connector.query_string_to_provider and creates Connector.query_to_provider
Connector Validate Query validate_query() Connector.status:
FEDERATING
Returns "False" if Connector.query_to_provider is empty
Connector Execute Search execute_search() Connector.status:
FEDERATING
Connects to the SearchProvider
Executes the search using Connector.query_to_provider
Stores the response in Connector.response
Connector Normalize Response normalize_response() Connector.status:
FEDERATING
Transforms Connector.response into a JSON list of dictionaries
Stores it in Connector.results
Connector Process Results process_results() Connector.status:
FEDERATING
READY
Processes Connector.results
Connector Save Results save_results() Connector.status:
READY
Returns "True"
Post-result processing search.py search() Search.status:
POST_RESULT_PROCESSING
FULL_RESULTS_READY
FULL_UPDATE_READY
Runs the post_result_processors
Updates Result objects

Search.Status

Normal States

Status Meaning
NEW_SEARCH The search object is to be executed immediately.
UPDATE_SEARCH The search object is to be updated immediately.
PRE_PROCESSING SWIRL is performing pre-processing for this search.
PRE_QUERY_PROCESSING SWIRL is performing pre-query processing for this search.
FEDERATING SWIRL is provisioning Celery workers with Connectors and waiting for results.
FULL_RESULTS SWIRL has received all results.
NO_RESULTS_READY SWIRL received no results from any provider.
PARTIAL_RESULTS SWIRL has received results from some providers, but not all.
POST_RESULT_PROCESSING SWIRL is performing post-result processing.
PARTIAL_RESULTS_READY SWIRL has processed results from responding providers.
PARTIAL_UPDATE_READY SWIRL has processed updated results from responding providers.
FULL_RESULTS_READY SWIRL has processed results for all specified providers.
FULL_UPDATE_READY SWIRL has processed updated results for all specified providers.
CANCELLING A cancel request was received; the search is shutting down cleanly.
CANCELLED The search was cancelled before completion.

Error States

Status Meaning
ERR_DUPLICATE_RESULT_OBJECTS More than one Result object was found; contact support for assistance.
ERR_NEED_PERMISSION The Django user does not have sufficient permissions to perform the requested operation. More: Permissioning Normal Users.
ERR_NO_ACTIVE_SEARCHPROVIDERS Search failed because no specified SearchProviders were active.
ERR_NO_QUERY_STRING The Search has no query_string.
ERR_NO_SEARCHPROVIDERS Search failed because no SearchProviders were specified.
ERR_PRE_QUERY_PROCESSING An error occurred during pre-query processing - check logs/celery-search-worker.log for details.
ERR_POST_RESULT_PROCESSING An error occurred during post-result processing - check logs/celery-search-worker.log for details.
ERR_ORCHESTRATOR_EXCEPTION The search orchestrator raised an unhandled exception during federation.
ERR_ORCHESTRATOR_DIED The search orchestrator process terminated unexpectedly during federation.
ERR_RESULT_NOT_FOUND A Result object that was expected to be found was not; contact support for assistance.
ERR_SUBSCRIBE_PERMISSIONS The user who created the Search object lacks permission to enable subscribe mode.

Key Module List

Interactive API Documentation

SWIRL provides interactive API documentation via Swagger UI, powered by drf-spectacular:

http://localhost:8000/swirl/api/docs/

This interface allows you to explore all available API endpoints, view request/response schemas, and test API calls directly from your browser.

SWIRL's API is mounted under two prefixes - /swirl/... and /api/swirl/... - that serve the same endpoints; either prefix works.

Additional APIs

Beyond the SearchProvider, Search, and Result APIs documented below, SWIRL 5 exposes these developer-facing endpoints. Full request/response schemas for each are in the Swagger / OpenAPI docs:

URL Explanation
/swirl/aiproviders/ List, create, and edit AIProvider objects (models, keys, roles)
/swirl/authenticators/ List, create, and edit Authenticator objects
/swirl/prompts/ List, create, and edit Prompt objects used by RAG and the Assistant
/swirl/pipelines/ List, create, and edit Pipeline objects (pre-query and post-result stage lists)
/swirl/workspaces/ List and manage Workspaces, members, and invites
/swirl/search/<id>/rerank/ Re-rank an existing search's results
/swirl/search/<id>/fetch_more/ Fetch additional results for an existing search
/swirl/rag-search/ Generate an AI summary over an existing search (see the Developer Guide)

SearchProvider Object

A SearchProvider defines a searchable source. It includes metadata identifying the connector type used to search the source, along with various configuration properties. Many properties are optional when creating a SearchProvider object, and default values are listed below.

Properties

Property Description Default Value (Example Value)
id Unique identifier for the SearchProvider Automatic (1)
name Human-readable name for the source "" ("Enterprise Search PSE")
description Description of the source, shown to users and used by the AI Search Assistant to decide when to search it (up to 2KB) "SearchProvider description" ("Searches the user's OneDrive files...")
owner Username of the Django user who owns the object Logged-in user ("admin")
workspace Optional Workspace that scopes this source; null means the provider is deployment-wide null ("legal")
groups List of Django group names permitted to use this provider [] (["legal-team"])
shared Boolean: if true, the SearchProvider can be searched by other users; if false, it is available only to the owner true (false)
date_created Timestamp when the SearchProvider was created Automatic (2022-02-28T17:55:04.811262Z)
date_updated Timestamp when the SearchProvider was last updated Automatic (2022-02-29T18:03:02.716456Z)
active Boolean: if true, the SearchProvider is used; if false, it is ignored in federated searches true (false)
default Boolean: if true, the SearchProvider is queried when no searchprovider_list is specified; if false, it must be explicitly included in searchprovider_list true (false)
authenticator Name (idp) of the Authenticator whose per-user token this source uses, e.g. Microsoft; null for sources that use credentials instead null ("Microsoft")
connector Name of the Connector to use for this source "RequestsGet" ("RequestsGet")
url URL or file path required by the Connector for this source (not validated) "" ("https://www.googleapis.com/customsearch/v1")
query_template String with optional {variable} placeholders for dynamic query construction. The Connector binds this template with url, query_string, query_mappings, and credentials at runtime. "{url}?q={query_string}" ("{url}?q={query_string}")
query_template_json JSON form of query_template, for connectors that take a JSON query body {} ({})
query_language Query language of the source, used when rewriting the query for it "Generic_Keyword" ("Generic_Keyword")
post_query_template For the RequestsPost Connector: valid JSON with a query marker used in the POST body {} ("query": "{query_string}","limit": "100")
http_request_headers Custom HTTP request headers for the source "" ("Accept": "application/vnd.github.text-match+json")
query_processors List of processors applied to the query before execution ["AdaptiveQueryProcessor"] (["AdaptiveQueryProcessor"])
query_mappings String defining query parameter mappings, dependent on the Connector "" ("cx=your-google-search-engine-key")
result_grouping_field Used with DedupeByFieldResultProcessor to define a field for duplicate suppression "" ("resource.conversationId")
result_processors List of processors normalizing results from this source ["MappingResultProcessor", "DateFinderResultProcessor", "CosineRelevancyResultProcessor"] (["MappingResultProcessor","CosineRelevancyResultProcessor"])
response_mappings JSONPath mappings to transform the source's response into a standardized JSON result set "" ("FOUND=searchInformation.totalResults, RETRIEVED=queries.request[0].count, RESULTS=items")
result_mappings Key-value mappings for result fields. See SP Guide, Result Mappings for details. "" ("url=link,body=snippet,cacheId,NO_PAYLOAD")
results_per_query Number of results requested per query from this source 10 (20)
credentials Credentials used for authentication (dependent on source) "" ("key=your-google-json-api-key")
eval_credentials Session-based credential variables for dynamic authentication "" ("session['my-connector-token']")
tags List of strings for categorizing SearchProviders [] (["News", "EnterpriseSearch"])
page_fetch_config_json Page Fetcher configuration for retrieving full document content from this source; see the AI Search Guide {} ({"cache": "false", "timeout": 10})
ephemeral_store_config_json Ephemeral result storage configuration; when ephemeral is true, results from this source are not persisted {"ephemeral": false} ({"ephemeral": false})
config Free-form JSON configuration; holds source-specific settings such as detailed instructions for the AI Search Assistant or the recent_files capability block {} ({})

The CosineRelevancyResultProcessor must follow MappingResultProcessor in the result_processors list.

APIs

URL Explanation
/swirl/searchproviders/ List all SearchProvider objects (newest first); create a new one using the POST form
/swirl/searchproviders/id/ Retrieve a specific SearchProvider object; delete it using the DELETE button; edit it using the PUT button

Search Object

A Search object is a JSON dictionary that defines a search operation. Each search has a unique ID and may be referenced by Result objects.

The only required property is query_string, which contains the search text. All other properties are optional and have default values. SWIRL executes searches asynchronously, updating properties like status and result_url in real-time.

Properties

Property Description Default Value (Example Value)
id Unique identifier for the Search Automatic (search_id=1)
owner Username of the Django user who owns the object Logged-in user (admin)
date_created Timestamp when the Search was created Automatic (2022-02-28T17:55:04.811262Z)
date_updated Timestamp when the Search was last updated Automatic (2022-02-28T17:55:07.811262Z)
query_string The query text (required) "" ("knowledge management")
query_string_processed Query text after pre-processing "" ("")
sort Search result ordering method relevancy (date)
results_requested Total number of results requested 10 (25)
searchprovider_list List of SearchProviders to query; an empty list searches all sources [] (["Enterprise Search Engines - Google PSE"])
subscribe If True, SWIRL updates the Search per the Celery-Beats schedule False (True)
status Execution status (see below) NEW_SEARCH (FULL_RESULTS_READY)
pre_query_processors List of processors applied before federation [] (["SpellcheckQueryProcessor"])
post_result_processors List of processors applied after federation. An empty list falls through to the system-default Pipeline, which is the source of truth for stage ordering. [] (["DedupeByFieldPostResultProcessor", "CosineRelevancyPostResultProcessor"])
result_url Link to the initial Result object using RelevancyMixer Automatic ("http://localhost:8000/swirl/results?search_id=17&result_mixer=RelevancyMixer")
new_result_url Link to updated Result object using RelevancyNewItemsMixer Automatic ("http://localhost:8000/swirl/results?search_id=17&result_mixer=RelevancyNewItemsMixer")
messages SearchProvider messages "" ("Retrieved 1 of 1 results from: Document DB Search")
result_mixer Mixer object used for result ordering RelevancyConfidenceMixer (Stack2Mixer)
retention Retention setting (0 = never expire, 1 = 1 hour, 2 = 1 day, 3 = 1 month, 4 = 5 minutes). See Search Expiration Service. 0 (2 for daily deletion)
tags Custom metadata attached to the Search object "" ({"query_string": "knowledge management", "tags": ["max_length:50"]})

Some special Search tags control query processing. For example, SW_RESULT_PROCESSOR_SKIP skips a specified processor: SW_RESULT_PROCESSOR_SKIP:DedupeByFieldResultProcessor

APIs

URL Explanation
/swirl/search/ List all Search objects (newest first); create a new one using the POST form
/swirl/search/id/ Retrieve a specific Search object; delete it using the DELETE button; edit it using the PUT button
/swirl/search/?q=some+query Create a Search object with default values except for query_string; redirects to result set; also accepts providers parameter
/swirl/search/?qs=some+query Create a Search object as above but return results synchronously; also accepts providers and result_mixer parameters
/swirl/search/?rerun=id Re-run a Search, deleting previously stored Results
/swirl/search/?update=id Update a Search with new results since the last execution

Result Objects

A Result object represents the normalized, re-ranked results for a single Search from a single SearchProvider. These objects are created at the end of the federated search process when a Search object is executed. They are the only SWIRL objects that have a foreign key (search.id).

Only Connectors should create Result objects.

Developers can manipulate individual Results as needed for their applications.

However, the goal of SWIRL (and federated search in general) is to provide unified results from all sources. SWIRL uses Mixers to streamline this process.

Properties

Property Description Example Value
id Unique identifier for the Result 1
owner Username of the Django user who owns the object admin
date_created Timestamp when the Result was created 2022-02-28T17:55:04.811262Z
date_updated Timestamp when the Result was last updated 2022-02-28T19:55:02.752962Z
search_id ID of the associated Search; multiple Result objects may share this ID 18
searchprovider Name of the SearchProvider that produced this result set "OneDrive Files - Microsoft 365"
query_to_provider Exact query sent to the SearchProvider https://www.googleapis.com/customsearch/v1?cx=google-search-engine-id&key=google-json-api-key&q=strategy
query_processors List of processors applied to the query (as specified in the SearchProvider) "AdaptiveQueryProcessor"
result_processors List of processors applied to the results (as specified in the SearchProvider) "MappingResultProcessor","CosineRelevancyResultProcessor"
result_processor_json_feedback List of processors that responded (See full result object)
messages Messages from the SearchProvider Retrieved 10 of 249 results from: OneDrive Files - Microsoft 365
status Readiness status of the result set READY
retrieved Number of results SWIRL retrieved from this SearchProvider 10
found Total number of results reported by the SearchProvider 2309
time Time taken by the SearchProvider to generate this result set (in seconds) 1.9
json_results Normalized JSON results from this SearchProvider (See below)

json_results

Field Description Example
swirl_rank SWIRL's relevancy ranking for this result 1
swirl_score Relevancy metric for this result. Included by default; add &explain=False to hide it. 1890.6471312936828
swirl_confidence_score Normalized confidence score (0-1) used by the RelevancyConfidenceMixer and RAG result selection 0.87
searchprovider Human-readable name of the SearchProvider "OneDrive Files - Microsoft 365"
searchprovider_rank SearchProvider's ranking for this result 3
searchprovider_score The source's own score for this result, when reported 7.12
title Source-reported title with highlighted search term matches German car industry to invest in <em>electric</em> <em>vehicles</em> ...
url URL for this result (reported by source and/or generated by SWIRL) http://pwc.com/etc
content_url URL the Page Fetcher uses to retrieve the full content, when different from url https://graph.microsoft.com/v1.0/drives/.../content
mimetype_url URL the Page Fetcher uses to determine the content's mimetype https://graph.microsoft.com/v1.0/drives/.../items/...
body Source-reported snippet with highlighted search term matches <em>Technology</em> strategy encompasses a full set of Consulting capabilities ...
date_published Source-reported publication date (if available, otherwise unknown). Used by the DateMixer. unknown
date_published_display Alternative publish date for display purposes, if mapped via SearchProvider. ... date_published=foo.bar.date1,date_published_display=foo.bar.date2 ...
date_retrieved Timestamp when SWIRL retrieved this result 2022-02-20 03:45:03.207909
author Source-reported author (if available) "CNN staff"
title_hit_highlights List of matched highlights in title
body_hit_highlights List of matched highlights in body
payload Dictionary of additional fields in the SearchProvider's response {}
explain Dictionary containing word stems, similarity scores, length adjustments, and hits metadata. Included by default; add &explain=False to hide it. {}

The PAYLOAD structure varies by SearchProvider. The caller must extract needed fields, typically by creating a new Processor or adding result_mappings.

APIs

URL Explanation
/swirl/results/ List all Result objects (newest first); create a new one using the POST form
/swirl/results/id/ Retrieve a specific Result object; delete it using the DELETE button; edit it using the PUT button
/swirl/results/?search_id=search_id Retrieve unified Results for a specific Search, ordered by the specified Mixer; also accepts result_mixer and page parameters

Connectors

Connectors are objects responsible for searching a specific type of SearchProvider, retrieving the results and normalizing them to the SWIRL format. This includes calling query and result processors.

Both connector.py and db_connector.py are base classes from which other connector classes are derived; requests.py is a wrapper called by RequestsGet. Two utility modules, mappings.py and utils.py, can be used by other Connectors.

Note that the requests.py connector automatically converts XML responses to JSON for mapping in SearchProvider configurations.

Connector Reference

The following table describes the included source Connectors:

Connector Description Inputs
BigQuery Searches Google BigQuery query_template, credentials (project JSON token file)
GenAI Asks LLM questions for direct answers credentials
Elastic Searches Elasticsearch url or cloud_id, query_template, index_name, credentials
M365OutlookMessages Uses the Microsoft Graph API to search M365 Outlook email None (per-user token via the Microsoft Authenticator)
M365OutlookCalendar Uses the Microsoft Graph API to search M365 calendar events None (per-user token via the Microsoft Authenticator)
M365OneDrive Uses the Microsoft Graph API to search M365 OneDrive files None (per-user token via the Microsoft Authenticator)
M365SharePointSites Uses the Microsoft Graph API to search M365 SharePoint sites None (per-user token via the Microsoft Authenticator)
MicrosoftTeams Uses the Microsoft Graph API to search Microsoft Teams messages None (per-user token via the Microsoft Authenticator)
Box Searches Box content credentials (client_id=<id>,client_secret=<client-secret>,bearer=<token>)
GoogleDriveFiles Searches Google Drive files via the Google Workspace APIs None (per-user token via the Google Authenticator)
GoogleGmailMessages Searches Gmail messages via the Google Workspace APIs None (per-user token via the Google Authenticator)
GoogleCalendarEvents Searches Google Calendar events via the Google Workspace APIs None (per-user token via the Google Authenticator)
GooglePeopleContacts Searches Google contacts via the Google Workspace APIs None (per-user token via the Google Authenticator)
MongoDB Searches a MongoDB Atlas search index mongo_uri, database_name, collection_name, credentials
OpenSearch Searches OpenSearch url, query_template, index_name, credentials
Oracle Tested against 23c Free (supports earlier versions) credentials
QdrantDB Searches Qdrant url (connection parameters), query_template, credentials
PineconeDB Searches Pinecone database url (connection parameters), query_template, credentials
PostgreSQL Searches PostgreSQL database url (connection parameters), query_template, credentials
RequestsGet Searches any web endpoint using HTTP/GET with JSON response, including Google PSE, SOLR, and Northern Light url, credentials
RequestsPost Searches any web endpoint using HTTP/POST with JSON response, including M365 url, credentials
Snowflake Searches Snowflake datasets credentials, database, warehouse
SnowflakeAI Queries Snowflake with AI/Cortex-style SQL templates credentials, query_template, query_mappings
Sqlite3 Searches SQLite3 databases url (database file path), query_template
SwirlCorpusConnector Searches the SWIRL Semantic Cache (Qdrant corpus collection) by vector similarity None (uses the deployment's SWIRL_CORPUS_* settings)
StubConnector Returns a canned response; used for testing None
LoadSimulationStub Generates synthetic results with configurable latency; used for load testing None

Connectors are specified in, and configured by, SearchProvider objects.

BigQuery

The BigQuery Connector uses the Google Cloud Python package.

The included BigQuery SearchProvider is configured for the Funding Data Set but can be adapted to other datasets.

{
    "name": "Company Funding Records - BigQuery",
    "active": false,
    "default": false,
    "connector": "BigQuery",
    "query_template": "select {fields} from `{table}` where search({field1}, '{query_string}') or search({field2}, '{query_string}');",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "fields=*,sort_by_date=fundedDate,table=funding.funding,field1=company,field2=city",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "result_mappings": "title='{company}',body='{company} raised ${raisedamt} series {round} on {fundeddate}. The company is located in {city} {state} and has {numemps} employees.',url=id,date_published=fundeddate,NO_PAYLOAD",
    "credentials": "/path/to/bigquery/token.json",
    "tags": [
        "Company",
        "BigQuery",
        "Internal"
    ]
}

More information: BigQuery Documentation

GenAI Connectors

SWIRL includes the GenAIConnector which can ask for direct answers from LLMs, as if they were regular SearchProviders. It returns at most one result.

The included SearchProvider is pre-configured with a "Tell me about: ..." prompt.

{
    "name": "GenAI - OpenAI",
    "active": false,
    "default": true,
    "connector": "GenAI",
    "url": "",
    "query_template": "",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "PROMPT='Tell me about: {query_to_provider}'",
    "result_processors": [
        "GenericResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "",
    "result_mappings": "",
    "results_per_query": 10,
    "credentials": "your-openai-API-key-here",
    "tags": [
        "GenAI",
        "Question"
    ]
}

Setting the GenAI Prompt or Role

The following query_mappings including quotes adjust the prompt or role passed to GenAI.

  • CHAT_QUERY_REWRITE_PROMPT: Customizes the prompt used to refine the query.
"CHAT_QUERY_REWRITE_PROMPT: Write a more precise query of similar length to this: {query_to_provider}"
  • CHAT_QUERY_REWRITE_GUIDE: Overrides the system role.
"CHAT_QUERY_REWRITE_GUIDE: You are a helpful assistant that responds like a pirate captain"
  • CHAT_QUERY_DO_FILTER: Enables/disables internal filtering of LLM responses.
"CHAT_QUERY_DO_FILTER: false"

For example:

"query_mappings": "CHAT_QUERY_REWRITE_PROMPT='Tell me about: {query_to_provider}',CHAT_QUERY_REWRITE_GUIDE='You are a helpful assistant that talks like a pirate captain but keeps it clean!'",

Do not use commas inside of a prompt passed in this manner.

Elastic & OpenSearch

The Elastic and OpenSearch Connectors use each engine's Python client.

Example: Elastic Cloud SearchProvider

{
    "name": "ENRON Email - Elastic Cloud",
    "connector": "Elastic",
    "url": "your-cloud-id-here",
    "query_template": "index='{index_name}', query={'query_string': {'query': '{query_string}', 'default_field': '{default_field}'}}",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "index_name=email,default_field=content,sort_by_date=date_published.keyword,NOT=true,NOT_CHAR=-",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "result_mappings": "url=_source.url,date_published=_source.date_published,author=_source.author,title=_source.subject,body=_source.content,_source.to,NO_PAYLOAD",
    "credentials": "verify_certs=[True|False],ca_certs=/path/to/cert/file.crt,username:password",
    "tags": [
        "Enron",
        "Elastic",
        "Internal"
    ]
}

Example: OpenSearch SearchProvider

{
    "name": "ENRON Email - OpenSearch",
    "active": false,
    "default": false,
    "connector": "OpenSearch",
    "url": "https://localhost:9200/",
    "query_template": "{"query":{"query_string":{"query":"{query_string}","default_field":"{default_field}","default_operator":"and"}}}",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "index_name=email,default_field=content,sort_by_date=date_published.keyword,NOT=true,NOT_CHAR=-",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "result_mappings": "url=_source.url,date_published=_source.date_published,author=_source.author,title=_source.subject,body=_source.content,_source.to,NO_PAYLOAD",
    "credentials": "verify_certs=[True|False],ca_certs=/path/to/cert/file.crt,username:password",
    "tags": [
        "Enron",
        "OpenSearch",
        "Internal"
    ]
}

JSONPaths in result_mappings are essential for Elastic and OpenSearch, as they embed results in a _source field unless configured otherwise.

See the SearchProvider Guide, Result Mappings for more details.

Use the Payload Field to store additional content.

FESS

FESS is a free enterprise search server that can be used to crawl web content, file systems and other data sources. Download FESS here: https://fess.codelibs.org/

SWIRL can query anything FESS indexes using the built-in HTTP server.

The following SearchProvider example can be used with FESS:

{
    "name": "Files - FESS",
    "description": "SearchProvider description",
    "active": true,
    "default": false,
    "authenticator": null,
    "connector": "RequestsGet",
    "url": "http://localhost:8080/api/v1/documents",
    "query_template": "{url}?x=x&q={query_string}",
    "query_template_json": {},
    "post_query_template": {},
    "http_request_headers": {
        "Content-Type": "application/json"
    },
    "page_fetch_config_json": {
        "cache": "false",
        "headers": {
            "User-Agent": "Swirlbot/1.0 (+http://swirlaiconnect.com)"
        },
        "timeout": 10
    },
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "DATE_SORT=sort=created.desc,RELEVANCY_SORT=sort=score",
    "result_grouping_field": "",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "RESULTS=data,FOUND=record_count",
    "result_mappings": "title=title,body=content_description,date_published=created,url=url",
    "results_per_query": 10,
    "credentials": "",
    "eval_credentials": "",
    "tags": [
        "Files",
        "FESS"
    ],
    "ephemeral_store_config_json": {
        "ephemeral": false
    },
    "query_language": "Generic_Keyword",
    "config": {}
}

This SearchProvider supports date sorted requests.

Modify the query_template to target different types and collections in FESS as noted in their API documentation.

Microsoft Graph

The Microsoft Graph Connector queries M365 content using OAuth2 authentication.

There are five pre-configured SearchProviders: * Outlook Messages * Calendar Events * OneDrive Files * SharePoint Sites * Teams Chat

Example: Outlook Messages SearchProvider

{
    "name": "Outlook Messages - Microsoft 365",
    "active": false,
    "default": true,
    "connector": "M365OutlookMessages",
    "url": "",
    "query_template": "{url}",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "NOT=true,NOT_CHAR=-",
    "result_grouping_field": "conversationId",
    "result_processors": [
        "MappingResultProcessor",
        "DedupeByFieldResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "",
    "result_mappings": "title=resource.subject,body=summary,date_published=resource.createdDateTime,author=resource.sender.emailAddress.name,url=resource.webLink,resource.isDraft,resource.importance,resource.hasAttachments,resource.ccRecipients[*].emailAddress[*].name,resource.replyTo[*].emailAddress[*].name,NO_PAYLOAD",
    "results_per_query": 10,
    "credentials": "",
    "eval_credentials": "",
    "tags": [
        "Microsoft",
        "Email"
    ]
}

MongoDB

The MongoDB Connector uses pymongo to connect to an Atlas Search index.

The included IMDB Movie Samples SearchProvider searches the sample_mflix.movies collection.

Example: MongoDB SearchProvider

{
    "name": "IMDB Movie Samples - MongoDB",
    "active": false,
    "default": false,
    "authenticator": "",
    "connector": "MongoDB",
    "url": "sample_mflix:movies",
    "query_template": "{'$text': {'$search': '{query_string}'}}",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "DATE_SORT=year,NOT_CHAR=-",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "result_mappings": "title=name,body=fullplot,date_published=released,date_published_display=year,author=directors[*],url=poster,lastupdated,genres[*],rated,runtime,languages[*],cast[*],writers[*],awards.text,imdb.rating,tomatoes.viewer.rating,tomatoes.critic.rating,NO_PAYLOAD",
    "results_per_query": 10,
    "credentials": "mongodb+srv://<mongodb-username>:<mongodb-password>@<mongdb-cluster>.mongodb.net/?retryWrites=true&w=majority",
    "eval_credentials": "",
    "tags": [
        "Movies",
        "MongoDB",
        "Internal"
    ]
}

By default, MongoDB SearchProvider uses MATCH_ALL, requiring all terms in a result. To switch to MATCH_ANY (Boolean OR behavior):

Option 1: Update query_mappings

"query_mappings": "DATE_SORT=year,NOT_CHAR=-,MATCH_ANY"

Option 2: Add a Search Tag

Instead of modifying the SearchProvider, apply a Search Tag.

Oracle

The Oracle Connector uses oracledb to connect to an Oracle instance.

The included Free Public DB SearchProvider has been tested with 23c Free and likely supports earlier versions.

PostgreSQL

The PostgreSQL Connector uses the psycopg2 driver.

Using the PostgreSQL Connector

In SWIRL 5, the PostgreSQL Connector is enabled by default - the psycopg2 driver ships with SWIRL, and the Connector is registered in CONNECTOR_CHOICES out of the box. (PostgreSQL is also a supported application database for SWIRL itself.)

To search a PostgreSQL database, add a PostgreSQL SearchProvider, such as the one configured for the Funding Dataset.

Example: PostgreSQL SearchProvider

{
    "name": "Company Funding Records - PostgreSQL",
    "default": false,
    "connector": "PostgreSQL",
    "url": "host:port:database:username:password",
    "query_template": "select {fields} from {table} where {field1} ilike '%{query_string}%' or {field2} ilike '%{query_string}%';",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "fields=*,sort_by_date=fundedDate,table=funding,field1=city,field2=company",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "result_mappings": "title='{company} series {round}',body='{city} {fundeddate}: {company} raised usd ${raisedamt}\nThe company is headquartered in {city} and employs {numemps}',date_published=fundeddate,NO_PAYLOAD",
    "tags": [
        "Company",
        "PostgreSQL",
        "Internal"
    ]
}

Notes - A fixed SQL query in query_template is acceptable. - Any static elements in the URL can be stored within query_template.

RequestsGet

The RequestsGet Connector uses HTTP/GET to fetch URLs. It supports optional authentication.

Example: Generic HTTP GET SearchProvider

{
    "name": "Sample HTTP GET Endpoint",
    "connector": "RequestsGet",
    "url": "http://hostname/site/endpoint",
    "query_template": "{url}&textQuery={query_string}",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "PAGE=start=RESULT_INDEX,DATE_SORT=sort=date",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "FOUND=count,RESULTS=results",
    "result_mappings": "body=content,date_published=date,author=creator",
    "credentials": "HTTPBasicAuth('your-username-here', 'your-password-here')",
    "tags": [
        "News"
    ]
}

Example: Google Programmable Search Engine (PSE)

{
    "name": "Enterprise Search Engines - Google PSE",
    "active": true,
    "default": true,
    "connector": "RequestsGet",
    "url": "https://www.googleapis.com/customsearch/v1",
    "query_template": "{url}?cx={cx}&key={key}&q={query_string}",
    "page_fetch_config_json": {
        "cache": "false",
        "headers": {
            "User-Agent": "Swirlbot/1.0 (+http://swirl.today)"
        },
        "timeout": 30
    },
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "cx=<your-Google-PSE-id-here>,DATE_SORT=sort=date,PAGE=start=RESULT_INDEX,NOT_CHAR=-",
    "result_processors": [
        "MappingResultProcessor",
        "DateFinderResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "FOUND=searchInformation.totalResults,RETRIEVED=queries.request[0].count,RESULTS=items",
    "result_mappings": "url=link,body=snippet,author=displayLink,cacheId,NO_PAYLOAD",
    "credentials": "key=<your-Google-API-key-here>",
    "tags": [
        "Web"
    ]
}

Example: SOLR Tech Products Collection

{
    "name": "techproducts - Apache Solr",
    "active": false,
    "default": false,
    "connector": "RequestsGet",
    "url": "http://localhost:8983/solr/{collection}/select?wt=json",
    "query_template": "{url}&q={query_string}",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "collection=techproducts,PAGE=start=RESULT_ZERO_INDEX,NOT=True,NOT_CHAR=-",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "FOUND=numFound,RESULTS=response.docs",
    "result_mappings": "title=name,body=features,response",
    "tags": [
        "TechProducts",
        "Solr"
    ]
}

To adapt RequestsGet to your JSON response, modify the JSONPaths in response_mappings using the format swirl_key=source-key. If results are wrapped in a dictionary, use RESULTS to extract them.

For more details, refer to: - SearchProvider Guide, Result Mappings - Payload Field for extra data storage.

RequestsPost

The RequestsPost Connector uses HTTP/POST to submit search forms. It supports optional authentication and is used by M365 connectors and other sources.

Example: Generic HTTP POST SearchProvider

{
    "name": "Sample HTTP POST Endpoint",
    "active": false,
    "default": false,
    "connector": "RequestsPost",
    "url": "https://xx.apis.it.h.edu/ats/person/v3/search",
    "query_template": "{url}?Query={query_string}",
    "post_query_template": {
        "fields": [
            "names.personNameKey",
            "names.firstName",
            "names.lastName"
        ],
        "conditions": {
            "names.name": "*{query_string}*"
        }
    },
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "NOT=true,NOT_CHAR=-",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "FOUND=count,RESULTS=results",
    "result_mappings": "titles=names[0].name,url=names[0].personNameKey,body='{names[0].name} ID#: {names[*].personNameKey}'",
    "results_per_query": 10,
    "credentials": "X-Api-Key=<your-api-key>",
    "tags": [
        "People"
    ]
}

Snowflake

The Snowflake Connector uses the snowflake-connector-python package to connect to a Snowflake instance.

The included Free Company Records SearchProvider is configured to search the FreeCompanyResearch dataset available in the Snowflake Marketplace.

Example: Snowflake SearchProvider

{
    "name": "Free Company Records - Snowflake",
    "connector": "Snowflake",
    "url": "<snowflake-instance-address>",
    "query_template": "SELECT {fields} FROM {table} WHERE {field1} ILIKE '%{query_string}%' AND NULLIF(TRIM(founded), '') IS NOT NULL ORDER BY TRY_TO_NUMBER(REGEXP_REPLACE(SPLIT_PART(size, '-', 1), '[^0-9]', '')) DESC;",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "fields=*,sort_by_date=founded,table=FREECOMPANYDATASET,field1=name",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "response_mappings": "",
    "result_mappings": "title='{name}  ({founded})',body='{name} was founded in {founded} in {country}. It has {size} employees and operates in the {industry} industry.',url='https://{linkedin_url}',date_published=founded,NO_PAYLOAD",
    "results_per_query": 10,
    "credentials": "<username>:<password>:FREE_COMPANY_DATASET:COMPUTE_WH",
    "tags": [
        "Company",
        "Snowflake"
    ]
}

Notes: - A fixed SQL query in the query_template is acceptable. - Static parameters can be stored in query_template instead of the URL.

SQLite3

The SQLite3 Connector uses the SQLite3 driver built into Python.

Example: SQLite3 SearchProvider

{
    "name": "Company Funding Records - SQLite3",
    "active": false,
    "default": false,
    "connector": "Sqlite3",
    "url": "db.sqlite3",
    "query_template": "select {fields} from {table} where {field1} like '%%{query_string}%%' or {field2} like '%%{query_string}%%';",
    "query_processors": [
        "AdaptiveQueryProcessor"
    ],
    "query_mappings": "fields=*,sort_by_date=fundeddate,table=funding,field1=city,field2=company",
    "result_processors": [
        "MappingResultProcessor",
        "CosineRelevancyResultProcessor"
    ],
    "result_mappings": "title='{company} series {round}',body='{city} {fundeddate}: {company} raised usd ${raisedamt}\nThe company is headquartered in {city} and employs {numemps}',date_published=fundeddate,NO_PAYLOAD",
    "tags": [
        "Company",
        "SQLite3"
    ]
}

Notes: - A fixed SQL query in the query_template is acceptable. - Static parameters can be stored in query_template instead of the URL.

Processing Pipelines

SWIRL Processing Pipelines

Processors execute in a sequence called a "pipeline." Pipelines are specified as JSON lists in their respective properties. SWIRL has four processing pipelines:

  • Search.pre_query_processors
  • SearchProvider.query_processors
  • SearchProvider.result_processors
  • Search.post_result_processors

The System Default Post-Result Pipeline

In SWIRL 5, when Search.post_result_processors is empty (the default), the system-default Pipeline runs these stages, in order:

[
    "CosineRelevancyPostResultProcessor",
    "DedupeByFieldPostResultProcessor",
    "DedupeBySimilarityPostResultProcessor",
    "VersionClusteringPostResultProcessor"
]

This pipeline ranks results, removes exact and near duplicates, and clusters document versions. Edit the System Default Post-Result Pipeline in the Django Admin to change it.

Query Processors

Query Processors modify queries. The field they operate on depends on where they are deployed.

Pipeline Reads Updates
Search.pre_query_processors Search.query_string Search.query_string_processed
SearchProvider.query_processors Search.query_string_processed <Connector>.query_string_to_provider

Included Query Processors

Processor Description Notes
AdaptiveQueryProcessor Rewrites queries based on query_mappings for a given SearchProvider Not for pre_query_processors
GenAIQueryProcessor Uses an LLM to rewrite queries, making them broader, more specific, boolean, or in another language
GenericQueryProcessor Removes special characters from queries
SpellcheckQueryProcessor Uses TextBlob to correct spelling errors Best used in SearchProvider.query_processors; avoid with Google PSE
NoModQueryProcessor Removes only leading SearchProvider Tags, leaving query terms unchanged For repositories allowing non-search characters (e.g., brackets)
TransformQueryProcessor Rewrites the query with configurable regex substitutions defined as paired SearchProvider tags (query_pattern:<regex> / query_replacement:<template>); the first matching rule wins SWIRL 5; pure configuration - no source-specific processor needed
RewriteQueryProcessor Applies an uploaded rewrite-type Query Transformation CSV, referenced as <name>.rewrite
SynonymQueryProcessor Applies an uploaded synonym-type Query Transformation CSV, referenced as <name>.synonym
SynonymBagQueryProcessor Applies an uploaded synonym-bag-type Query Transformation CSV, referenced as <name>.bag
RemovePIIQueryProcessor Removes PII entities from queries without replacing them
RedactPIIQueryProcessor Replaces PII entities in queries with type tags (e.g., <PERSON>)

GenAIQueryProcessor

The GenAIQueryProcessor calls an LLM with the user's query and a custom prompt to enable rewriting, translation, phrase detection, and more.

Configuring the SearchProvider

To use the GenAIQueryProcessor with a specific SearchProvider, add it to the SearchProvider's query_processors list:

    "query_processors": [
        "AdaptiveQueryProcessor",
        "GenAIQueryProcessor"
    ]

To alter the query sent to all SearchProviders, add it to the Search.pre_query_processors list.

{
    "query_string": "<user-query-string>",
    "pre_query_processors": ["GenAIQueryProcessor"]
}

Note that the example above only applies to calling the SWIRL API. Please contact support for instructions on how to configure this behavior with the Galaxy UI.

Configuring the QueryProcessor

The GenAIQueryProcessor supports the same tags and configuration options as the GenAIConnector but using a colon (':') as a delimiter.

For example:

"tags": [
    "CHAT_QUERY_REWRITE_PROMPT:If this query is in Japanese, tokenize it, and output ONLY the tokenized japanese, NOTHING ELSE -> {query_string}",
    "CHAT_QUERY_REWRITE_GUIDE:You are a speedy tokenizer!",
    "CHAT_QUERY_DO_FILTER:False"
],

Result Processors

Result Processors transform source results into SWIRL format, as defined in swirl/processors/utils.py.

Included Result Processors

Processor Description Notes
GenericResultProcessor Copies results from source format to SWIRL format by exact name match Use for sources that don’t require mapping
MappingResultProcessor Maps results to SWIRL format using SearchProvider.result_mappings Default
LenLimitingResultProcessor Truncates long title and body fields, appending an ellipsis ("..."). If truncated, stores full response in body_full in payload. Default limit: 512 characters, configurable via SearchProvider tag (max_length:256). Should follow MappingResultProcessor
CleanTextResultProcessor Removes non-alphanumeric characters (e.g., HTML/Markdown syntax) Should run before LenLimitingResultProcessor
DateFinderResultProcessor Extracts dates from result body and assigns them to date_published if missing Detects formats like:
06/01/23, jun 1, 2023, 06-01-2023
AutomaticPayloadMapperResultProcessor Identifies suitable title, body, and date_published values in source data Place after MappingResultProcessor. Use DATASET directive for single response storage in payload.dataset.
RequireQueryStringInTitleResultProcessor Removes results lacking query_string_to_provider in the title Place after MappingResultProcessor. Default for "LinkedIn - Google PSE"
FetchURLForBodyResultProcessor Fetches the result's full content from its URL (or the Page Fetcher content_url) and stores it in body Required for sources whose search response returns only titles or snippets (e.g., Box)
RedactPIIResultProcessor Redacts PII in all result fields, including payload strings, replacing entities with tags (e.g., "James T. Kirk""<PERSON>") If applied before CosineRelevancyResultProcessor, PII terms won't affect ranking. Uses Presidio.
DedupeByFieldResultProcessor Groups results from this source that share the same value in the field named by SearchProvider.result_grouping_field, returning one result per group Used by the M365 Outlook Messages SearchProvider (conversationId)
EntityExtractingResultProcessor Extracts named entities from result fields using the reader LLM and stores them in the result's entities dictionary Fields to scan are configurable via the entity_fields SearchProvider tag

Post Result Processors

PostResultProcessors modify stored result data. They operate only on processed results saved by each connector.

CosineRelevancyPostResultProcessor

SWIRL includes a cosine vector similarity relevancy model based on spaCy. The source code is found in swirl/processors/relevancy.py.

Relevancy Model

  • Matches word stems using nltk.
  • Scores fields defined in SWIRL_RELEVANCY_CONFIG in swirl_server/settings.py.
  • Aggregates similarity of:
  • Entire query vs. field (highest match in any sentence).
  • Entire query vs. text window around field match.
  • 1- and 2-word query combinations vs. text window around match.
  • Weights fields as defined in SWIRL_RELEVANCY_CONFIG.
  • Further weights window-text matches by match length.
  • Provides a minor boost based on the original SearchProvider's rank:
  • $1/(1+\sqrt{SearchProvider.rank})$
  • Normalizes result length against the median of all results (result_length_adjust in explain).
  • Normalizes query length compared to all executed queries (query_length_adjust in explain).

Score Interpretation

The SWIRL score is relative: a higher score indicates greater contextual relevance. Scores are not comparable across queries.

Tip: To translate a score into confidence, set the highest result as 1.0, then divide other scores by it.

SWIRL provides: - swirl_rank (1 to N, where N is total results). - searchprovider_rank (rank assigned by the source).

Ties in relevancy ranking are broken by date_published and searchprovider_rank.

Relevancy Ranking Process: 1. SearchProvider.result_processors ranks results asynchronously per SearchProvider. 2. Search.post_result_processors finalizes ranking across results, adjusting for length and score normalization.

The CosineRelevancyPostResultProcessor must be included in Search.post_result_processors, after result mappings but before any processor dependent on swirl_score.

Example Configuration

"result_processors": [
    "MappingResultProcessor",
    "DateFinderResultProcessor",
    "CosineRelevancyResultProcessor"
]

Relevancy Implementation Notes

Implementation details of the relevancy pipeline that are useful when debugging scores:

  • Sparse-vector detection. Before computing cosine similarity, the processor checks spaCy's has_vector and vector_norm properties; only genuinely vector-less inputs fall back to a constant score.
  • NOT term handling. When a NOT token flags a result in Pass 2 of CosineRelevancyPostResultProcessor, only that result is suppressed; the provider's remaining results are scored normally.
  • Quoted-phrase relevancy. Quoted sub-strings in the query are detected before quote-stripping and prepended as highest-priority targets to both query_stemmed_target_list and query_target_list, so results matching the exact phrase outrank results that only match the scattered words.
  • Performance. nlp(query) is computed once per search, not once per (result × field), and the cheap stem_string() + match_any() check runs before the expensive per-field nlp() call - fields with no stem overlap with the query skip NLP entirely.

Additional Post Result Processors

DropIrrelevantPostResultProcessor

Drops results with swirl_score < settings.MIN_SWIRL_SCORE (default: 500) and results lacking a swirl_score. Not enabled by default.

Note: Galaxy UI may not correctly display the result count when using this processor.

RedactPIIPostResultProcessor

Identical to RedactPIIResultProcessor, but processes all results in a search instead of per SearchProvider.

DedupeBySimilarityPostResultProcessor

Detects near-duplicates by similarity of title and body. By default (SWIRL_DEDUPE_GROUP_NOT_DROP=True) near-duplicates are grouped rather than dropped; the similarity threshold is SWIRL_DEDUPE_SIMILARITY_MINIMUM (default 0.95). Part of the system-default post-result Pipeline.

VersionClusteringPostResultProcessor

Clusters versions of the same document across sources (using the Semantic Cache's document signals), so the Galaxy UI can present one result per document with its versions grouped. Part of the system-default post-result Pipeline.

FetchURLPostResultProcessor

Fetches full content for results via the Page Fetcher after federation completes, across all providers in the search. Not enabled by default.

WriteToFileSystemPostResultProcessor

Writes the search's results to the local filesystem. Not enabled by default.

Mixers

Mixers organize search results into a structured order.

Mixer Description Notes
RelevancyMixer Sorts by relevancy score (descending), then source rank (ascending). Depends on relevancy_processor in search.post_result_processors.
RelevancyConfidenceMixer Sorts by the normalized confidence score (descending). Default result_mixer in SWIRL 5.
RelevancyNewItemsMixer Same as RelevancyMixer, but hides results missing the new field from Search updates. Default for search.new_result_url.
DateMixer Sorts by date_published. Omits results with "unknown" dates. Use for date-sorted results.
DateNewItemsMixer Same as DateMixer, but hides results missing the new field. Default for search.new_result_url when sorting by date.
RoundRobinMixer Alternates results from each SearchProvider; equivalent to Stack1Mixer. Good for cross-sectioned results or date sorting.
Stack1Mixer Alternates results from each SearchProvider, one at a time. Good for cross-sectioned data.
Stack2Mixer Alternates results, taking two per SearchProvider. Good for 4-6 sources.
Stack3Mixer Alternates results, taking three per SearchProvider. Good for few sources.
StackNMixer Alternates results, taking N per SearchProvider (default: results requested ÷ number of providers responding). Good for fewer providers.

Date Mixer

For date_published-sorted results, use DateMixer.

SWIRL Results, Date Mixer

Example:

http://localhost:8000/swirl/results?search_id=1&result_mixer=DateMixer

NewItems Mixers

NewItems Mixers filter results to only those with the new field. They also report hidden results.

To mark all results as "read" (removing new status), add &mark_all_as_read=1:

http://localhost:8000/swirl/results/?search_id=1&result_mixer=DateNewItemsMixer&mark_all_as_read=1

The mixer will then return 0 results but will return new results when the search updates.

Using Mixers

Mixers combine and order Result objects. For example: - Stack1Mixer alternates between sources. - DateMixer sorts by date_published.

To apply the default Mixer:

http://localhost:8000/swirl/results/?search_id=1

To specify a different Mixer, append &result_mixer=mixer-name:

http://localhost:8000/swirl/results/?search_id=1&result_mixer=Stack1Mixer

Mixer Response Format

Field Description
messages All messages from the Search and SearchProviders.
info Found/Retrieved counts per SearchProvider.
info - search Search metadata, processed query, re-run links, and re-score links.
info - results Result count, next/previous page URLs.
results Mixed results from the search.

Sample Data Sets

Funding Data Set

The TechCrunch Continental USA funding data set is sourced from Insurity SpatialKey. It is included in SWIRL as Data/funding_db.csv and processed with DevUtils/fix_csv.py before loading into SQLite3.

Loading into SQLite3

  1. Activate sqlite_web from the swirl-home directory:
sqlite_web db.sqlite3
  1. Open http://localhost:8080/ in a browser if it does not open automatically.
  2. Enter "funding" in the text box in the upper right and click Create.
  3. Click Choose File and select Data/funding_db.csv.
  4. Leave "Yes" in the confirmation box.
  5. Click Import.

Sqlite loading funding dataset

  1. Load the Funding DB SQLite3 SearchProvider as described in the SearchProvider Guide.

Loading into PostgreSQL

  1. Create a table using SQL or Postico:
CREATE TABLE funding (
    id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    permalink TEXT,
    company TEXT,
    numemps TEXT DEFAULT '0',
    category TEXT,
    city TEXT,
    state TEXT,
    fundeddate DATE,
    raisedamt NUMERIC DEFAULT '0',
    raisedcurrency TEXT,
    round TEXT
);

CREATE UNIQUE INDEX funding_pkey ON funding(id);
  1. Import the CSV:
COPY funding(permalink,company,numemps,category,city,state,fundeddate,raisedamt,raisedcurrency,round) 
FROM '/path/to/Data/funding_db.csv' 
DELIMITER ',' CSV HEADER;
  1. Load the Funding DB PostgreSQL SearchProvider as described in the SearchProvider Guide.

Loading into BigQuery

  1. Create a table with the following schema:

BigQuery Funding DB Schema in Console

  1. Load the CSV using Google's BigQuery CSV Import Guide.
  2. Load the Funding DB BigQuery SearchProvider as described in the SearchProvider Guide.

Enron Email Data Set

This dataset includes 500,000+ emails from 150 former Enron employees. It is available on Kaggle and Carnegie Mellon.

Loading into Elastic or OpenSearch

  1. Download and extract the Enron email dataset.
  2. Move emails.csv to your swirl-home directory.
  3. Create a new index named 'email' using the Elastic/OpenSearch console:
PUT /email

To index Enron data into Elastic, update the load script to include a valid certificate path.

  1. Modify DevUtils/index_email_elastic.py (line 37):
## Insert path to Elastic cert below
ca_certs = "<PATH-TO-CERT>"
  1. Index the emails:

For Elastic:

python DevUtils/index_email_elastic.py emails.csv -p elastic-password

For OpenSearch:

python DevUtils/index_email_opensearch.py emails.csv -p admin-password
  1. Verify the index in the development console:
GET _search
{
  "query": {
    "match_all": {}
  }
}

Example Response:

{
  "took": 38,
  "timed_out": false,
  "_shards": {
    "total": 6,
    "successful": 6,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 6799,
      "relation": "eq"
    },
    "max_score": 1.0,
    "hits": [
      {
        "_index": "email",
        "_id": "c13MwoUBmlIzd81ioZ7H",
        "_score": 1.0,
        "_source": {
          "url": "allen-p/_sent_mail/118.",
          "date_published": "2000-09-26 09:26:00.000000",
          "author": "<name>",
          "to": "<email-address>",
          "subject": "Investment Structure",
          "content": "---------------------- Forwarded by ..."
        }
      }
    ]
  }
}