Overview
The Search API provides fast, flexible product search using Dgraph’s graph database capabilities. It supports custom queries for product search, related products, and complex relationship-based filtering.
Endpoints
Primary Search
Executes a custom Dgraph query for product search.
POST /api/v2/related-products
Finds related products based on relationships and attributes.
Dgraph Integration
The search functionality uses Dgraph, a native graph database that enables complex queries with predicates and filters.
Connection Configuration
from settings import DGRAPH_SERVER_CLIENT
import pydgraph
client_stub = pydgraph.DgraphClientStub( DGRAPH_SERVER_CLIENT )
client = pydgraph.DgraphClient(client_stub)
Queries are executed with:
Read-only transactions for safety
Best-effort mode for improved performance
1-second timeout for fast responses
Long-term caching via Beaker
Send Dgraph queries as JSON in the request body:
{
"query" : "{
search(func: type(Product)) @filter(eq(status, 1)) {
uid
product_id
name
price
spl_price
images
category {
name
}
}
}"
}
Search Examples
Search Products by Name
{
products ( func : type ( Product )) @filter (regexp(name, /tshirt/i)) {
uid
product_id
name
price
spl_price
sale_url
images
}
}
Search with Category Filter
{
products ( func : type ( Product )) @cascade {
uid
product_id
name
price
category @filter (eq(category_id, 123)) {
category_id
name
}
}
}
Search by Price Range
{
products ( func : type ( Product )) @filter (ge(spl_price, 500) AND le (spl_price, 2000)) {
uid
product_id
name
price
spl_price
images
}
}
Search with Multiple Filters
{
products ( func : type ( Product )) @filter (
eq(status, 1) AND
ge (spl_price, 500) AND
regexp (name, /premium/i)
) {
uid
product_id
name
price
spl_price
category {
name
}
tags {
name
}
}
}
Find products related by category, tags, or artist:
{
"query" : "{
var(func: uid(0x123)) {
category {
~category @filter(type(Product)) {
related as uid
}
}
}
related(func: uid(related), first: 10) {
uid
product_id
name
price
images
}
}"
}
Data Model
Products in Dgraph have the following key predicates:
Unique product identifier from MySQL
Product status (1 = active, 0 = inactive)
References to category nodes
References to variant nodes
References to pricelist nodes for exclusive pricing
Caching
Search queries are cached using Beaker’s long-term cache region:
@cache_region ( 'long_term' , 'search' )
def query_dgraph ( query ):
# Execute query with caching
Cache key is generated from the query string. Cache duration is configured in your cache settings.
For optimal search performance:
Use specific filters to reduce result set size
Leverage indexed predicates (product_id, status, price)
Use first: N to limit results
Enable best-effort transactions for read-only queries
Cache frequently-used queries
Data Synchronization
Products are synced to Dgraph via Celery background tasks:
# Sync product to Dgraph
@app.task
def syncDgraphProduct ( product_ids ):
sync_product = SyncProduct()
sync_product.product_ids = product_ids
sync_product.make_product_categories()
sync_product.make_product_tags()
sync_product.make_product_variants()
sync_product.set_payload()
sync_product.insert_into_dgraph()
See tasks.py:111 for the complete implementation.
Elasticsearch Alternative
While Dgraph is the primary search engine, the system also supports Elasticsearch:
SEARCH_ENDPOINT = os.environ.get( 'SEARCH_ENDPOINT' )
ELASTIC_SEARCH_HOST = os.environ.get( 'ELASTIC_SEARCH_HOST' )
Elasticsearch is used for:
Full-text product search
User widget data indexing
Visit logging and analytics
Error Handling
The search API handles errors gracefully:
{
"status" : "error" ,
"message" : "Exception in query_dgraph: connection refused"
}
Common errors:
Connection timeout - Dgraph server unreachable
Query syntax error - Invalid Dgraph query format
Empty result - Query matched no nodes
Queries have a 1-second timeout (see DgraphController.py:17). Complex queries may need optimization to complete within this limit.
Advanced Queries
Faceted Search
{
var ( func : type ( Product )) @filter (eq(status, 1)) {
uid
}
categories ( func : uid ( var )) @groupby (category) {
count (uid)
}
tags ( func : uid ( var )) @groupby (tags) {
count (uid)
}
}
Aggregate Queries
{
products ( func : type ( Product )) @filter (eq(category_id, 123)) {
avg_price : avg (spl_price)
min_price : min (spl_price)
max_price : max (spl_price)
count : count (uid)
}
}
GraphQL API Alternative querying method for product data
Celery Tasks Background sync operations for search indexing