Using Loci with Elasticsearch

Elasticsearch is a popular distributed search engine that provides real-time search and analytics. When combined with the detailed tags and metadata for 3D assets provided by Loci, Elasticsearch becomes a powerful and scalable tool for asset search and discovery.

👍

This guide assumes you are starting from scratch with Elasticsearch. If you already have Elasticsearch running, you can proceed directly to Step 4.

Though this guide is written for the Elasticsearch Python client, the concepts are generic and can be applied with any Elasticsearch client.

Step 1: Install & Set Up Your Elasticsearch Cluster

First, we must install and set up Elasticsearch. Visit the Elasticsearch download page and follow the installation instructions provided for your system. Once finished, you can verify Elasticsearch is up and running by visiting http://localhost:9200 in the browser. The page should display a snippet which looks similar to the below:

{
  "name" : "Name",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "led3TLKcRDXyLDcKsPCALA",
  "version" : {
    "number" : "8.12.0",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "1023f706gr3520262002123h1h6h5c0fbcddfbc9",
    "build_date" : "2024-01-11T10:05:27.953830042Z",
    "build_snapshot" : false,
    "lucene_version" : "9.9.1",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "For Search"
}

Step 2: Install Elasticsearch's Python Client

It's now time to start writing the script that will populate our new Elasticsearch database with data provided by Loci's API! First, install the Elasticsearch client for Python:

pip install elasticsearch

Step 3: Configure Elasticsearch

We can now start writing our script. Our goal is to tag assets using Loci, and to then add this tag data directly to our Elasticsearch database. To begin, we will first add some code that will configure the Elasticsearch index. This will look like the below:

from elasticsearch import Elasticsearch

SEARCH_URL = "http://localhost:9200"
ELASTICSEARCH_INDEX = "my_loci_index"  # the name of the index to be created or used

es = Elasticsearch(ELASTICSEARCH_URL)

Although out of scope for this tutorial, it is also possible to configure your index settings and mappings using an Elasticsearch GUI such as Kibana or Grafana.

Step 4: Tag your asset(s) with Loci!

The next part of our script will call the Loci API to tag our assets. In the example below, we are tagging an asset stored locally located at /path/to/my_asset_file.glb. You can find out more about using the Loci API in the Quickstart Guide and API Documentation.

import requests

LOCI_API_URL = "https://loci-api.com/3d/tag"
LOCI_API_KEY = ""  # your API key

loci_headers = {"x-api-key": LOCI_API_KEY}

def tag_asset(file_path):
    with open(file_path, "rb") as file:
        response = requests.post(LOCI_API_URL, headers=loci_headers, files={"file": file})

    return response.json()
    
      
tagged_asset = tag_asset("/path/to/my_asset_file.glb")

The response from Loci's API will include the asset filename and AI generated tags, which will be used to populate the Elasticsearch index. Loci also returns other useful information about your asset, including colors and geometry metadata (such as the number of vertices and polygons).

{
  "filename": "my_test_asset.glb",
  "tags": [
    "mythological creature",
    "fantasy creature",
    "superhero",
    "jumpsuit",
    "standing"
  ]
}

Step 5: Save your data to Elasticsearch

The next step is to save the data returned by the Loci API to our Elasticsearch index. We can do this with a call to the index function, like below:

def index_asset(filename, tags):
    # Prepare the document for Elasticsearch
    doc = {"filename": filename, "tags": tags}
    # index the document into Elasticsearch
    es.index(index=ELASTICSEARCH_INDEX, id=filename, document=doc)
    

index_asset(tagged_asset["filename"], tagged_asset["tags"])

Once this has run, the asset will be indexed and searchable via Elasticsearch using both the filename and the assigned tags.

Our final code block, combining both the Loci API call and the indexing to Elasticsearch, will look like this:

import requests
from elasticsearch import Elasticsearch

LOCI_API_URL = "https://loci-api.com/3d/tag"
LOCI_API_KEY = ""  # your API key

ELASTICSEARCH_URL = "http://localhost:9200"
ELASTICSEARCH_INDEX = "my_loci_index"  # the name of the index to be created or used

# Setup Elasticsearch client
es = Elasticsearch(ELASTICSEARCH_URL)


loci_headers = {"x-api-key": LOCI_API_KEY}
def tag_asset(file_path):
    with open(file_path, "rb") as file:
        response = requests.post(LOCI_API_URL, headers=loci_headers, files={"file": file})

    return response.json()


def index_asset(filename, tags):
    # Prepare the document for Elasticsearch
    doc = {"filename": filename, "tags": tags}
    # index the document into Elasticsearch
    es.index(index=ELASTICSEARCH_INDEX, id=filename, document=doc)


file_path = "/path/to/my_asset_file.glb"  # Your file path here
tagged_asset = tag_asset(file_path)
index_asset(tagged_asset["filename"], tagged_asset["tags"])

Step 6: Search and Discover!

Once this script has been executed, the tagged file will now be discoverable through Elasticsearch using its generated tags. We can verify this by running the following code snippet:

import requests
from elasticsearch import Elasticsearch

ELASTICSEARCH_URL = "http://localhost:9200"
ELASTICSEARCH_INDEX = "my_loci_index"  # the name of the index to be created or used

es = Elasticsearch(ELASTICSEARCH_URL)

search_query = {
    "query": {
        "match": {
            "tags": "sculpture"  # Example tag - replace with a tag that you would like to search for!
        }
    }
}

response = es.search(index=ELASTICSEARCH_INDEX,  body=search_query)

for doc in response['hits']['hits']:
    print(doc['_source'])

Elasticsearch will now instantly return any asset(s) that match the tag that we passed into our query. With Loci, it's that easy to make your 3D asset collection instantly discoverable.