Skip to content

Facet by a nested join field leads to issues #2863

@dejonghee

Description

@dejonghee

Bug Description

When you have a data model with multiple joins (product -> variant -> stock), faceting on the nested joins (e.g. a property 'inStock' on the Stock level) leads to timeouts/cancelled requests.

Reproduction Steps

@hostname = localhost:46675
@apiKey = typesense-api-key

DELETE http://{{hostname}}/collections/products
X-TYPESENSE-API-KEY: {{ApiKey}}

###

DELETE http://{{hostname}}/collections/variants
X-TYPESENSE-API-KEY: {{ApiKey}}

###

DELETE http://{{hostname}}/collections/stock
X-TYPESENSE-API-KEY: {{ApiKey}}

### Create Products Collection.

POST http://{{hostname}}/collections
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "name": "products",
  "fields": [
    {"name": "name", "type": "string", "facet": false, "sort": true},
    {"name": "brand", "type": "string", "facet": true, "sort": true}
  ],
  "metadata": {"revision": "d9765d97-91a8-4042-bbdf-50697f0876ed"}
}

### Create Alias for Products.

PUT http://{{hostname}}/aliases/productsalias
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "collection_name": "products"
}

### Create Variants Collection.

POST http://{{hostname}}/collections
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "name": "variants",
  "fields": [
    {"name": "product_id", "type": "string", "facet": true, "reference": "productsalias.id", "async_reference": true},
    {"name": "color", "type": "string", "facet": true, "sort": true}
  ],
  "metadata": {"revision": "8a8793bf-7592-48fc-ac14-ab0896bc9ba0"}
}

### Create Alias for Variants.

PUT http://{{hostname}}/aliases/variantsalias
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "collection_name": "variants"
}

### Create Stock Collection.

POST http://{{hostname}}/collections
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "name": "stock",
  "fields": [
    {"name": "variant_id", "type": "string", "reference": "variantsalias.id"},
    {"name": "inStock", "type": "bool", "facet": true, "sort": true}
  ]
}

### Create Alias for Stock.

PUT http://{{hostname}}/aliases/stockalias
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "collection_name": "stock"
}

### Index Products.

POST http://{{hostname}}/collections/productsalias/documents/import?action=upsert
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{"id":"p-1","name":"Product 1","brand":"A"}
{"id":"p-2","name":"Product 2","brand":"A"}
{"id":"p-3","name":"Product 3","brand":"B"}
{"id":"p-4","name":"Product 4","brand":"C"}

### Index Variants.

POST http://{{hostname}}/collections/variantsalias/documents/import?action=upsert
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{"id":"p-1-v-1","product_id":"p-1","color":"Red"}
{"id":"p-1-v-2","product_id":"p-1","color":"Green"}
{"id":"p-1-v-3","product_id":"p-1","color":"Blue"}
{"id":"p-2-v-1","product_id":"p-2","color":"Pink"}
{"id":"p-2-v-2","product_id":"p-2","color":"Red"}
{"id":"p-3-v-1","product_id":"p-3","color":"Red"}
{"id":"p-3-v-2","product_id":"p-3","color":"Blue"}
{"id":"p-4-v-1","product_id":"p-4","color":"Red"}

### Index Stock.

POST http://{{hostname}}/collections/stockalias/documents/import?action=upsert
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{"id":"p-1-v-1-s-1","variant_id":"p-1-v-1","inStock":true}
{"id":"p-1-v-2-s-2","variant_id":"p-1-v-2","inStock":false}
{"id":"p-4-v-1-s-1","variant_id":"p-4-v-1","inStock":true}

### Facet on 'inStock'

POST http://{{hostname}}/multi_search
X-TYPESENSE-API-KEY: {{apiKey}}
Content-Type: application/json

{
  "searches": [
    {
        "collection": "productsalias",
        "q": "*",
        "filter_by": "id:* || $variantsalias(id:*) || $variantsalias($stockalias(id:*))",
        "facet_by": "brand, $variantsalias(color), $variantsalias($stockalias(inStock))",
        "per_page": 5
    }
  ]
}

The last '$variantsalias($stockalias(inStock))' in facet_by is the part which leads to issues.

As an alternative I tested the following query, which returns no facet values for 'inStock':

{
  "searches": [
    {
        "collection": "productsalias",
        "q": "*",
        "filter_by": "id:* || $variantsalias(id:*) || $variantsalias($stockalias(id:*))",
        "facet_by": "brand, $variantsalias(color), $stockalias(inStock)",
        "per_page": 5
    }
  ]
}

Expected vs Actual

Expected behavior
The correct facet values and facet counts should be returned.

Actual behavior
Typesense does not respond.

Environment

  • Typesense version: e.g. v30.1

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions