Skip to main content

Dynamic metadata storage

Project description

image image image Code Coverage Actions status

dyna-store

Efficient handling of high cardinality metadata.

In order to explain the main concept, let's go through an example:

How it works

schema

Given the id cwxpd-3BDb2jXPk:

  1. cwxpd is the template id. We can use it to retrieve the template from a database.
  2. the userId is an integer encoded in the id as 3BD -> 213123
  3. the timestamp is an datetime encoded in the id as b2jXPk -> 2024-05-22 15:13:56+00:00
  4. the id can be fully parsed, using both the high cardinality fields (user_id, timestamp) from the id itself and the other fields (algorithm, promoted) in the template.

Use case

We have an online shopping website, where user are shown recommended products. Each recommendation can lead to a bunch of user events (viewed, clicked, purchased, etc.). These events are stored in a database for further analysis. For each event, we want to be able to relate it to the recommendation that led to it - in particular when the recommendation was made, with which algorithm, etc.

Without dyna-store

An approach would be to store all the recommendations in a database table:

id userId timestamp algorithm
BShivYLGif user1 1716384775942 algo-1
5SvIjZIXMm user1 1716384793233 algo-2
DkBoUmvMs0 user2 1716384489455 algo-2
Nm8NabCct8 user2 1716384483847 algo-2
5ZO053OGpX user2 1716384448985 algo-2

Each recommendation would have a unique identifier (the primary key), maybe generated by the database.

Then, we can attach to each event the recommendation id. At any point we can query the recommendation table to get the details of the recommendation.

This works, but has some limitation: the recommendation table can grow very large:

  • if you are computing recommendations on the fly, a single user session can generate a lot of recommendations
  • if you are pre-computing recommendations (to ensure a fast first page view), that's also a lot of data to every day.

With dyna-store

Dyna store intend to address this limitation, by:

  • store less information in the database
  • store more information in the recommendation id itself

We will first split our fields between two categories:

  • the low cardinality field (algorithm in our example) - they don't have many different values and can be stored in the database
  • the high cardinality field (userId, timestamp in our example) - they have many different values and will be stored in the id.

Then in the databse we will store the low cardinality fields, as well as the information needed to parse the informations contained in the id in a new template table:

id userId timestamp algorithm
BShivYLGif { __hcf: 1, i: 0, l: 5, t: "string" } { __hcf: 1, i: 5, l: 5, t: "datetime" } algo-1
5SvIjZIXMm { __hcf: 1, i: 0, l: 5, t: "string" } { __hcf: 1, i: 5, l: 5, t: "datetime" } algo-2

then the recommendation id will contain two part:

  • the database id of the template - BShivYLGif
  • the high cardinality fields, b62 encoded - user1dXed which will give us the recommendation id BShivYLGif-user1dXed

This id will be then attached to each event. From the id we can regenerate the original metadata, assuming we have access to the templates table. In some cases, that can lead to a drastic reduction of the amount of data stored in the database.

Usage

from datetime import datetime

from dyna_store import DynaStore, HighCardinality, LowCardinality, Metadata, MetadataId
from pydantic import BaseModel

# create a pydantic model for your recommendations metadata
# you need to wrap your fields in either HighCardinality or LowCardinality
# HighCardinality fields will be stored in the id
# LowCardinality fields will be stored in the templates
class Recommendation(BaseModel):
    userId: HighCardinality[str]
    timestamp: HighCardinality[datetime]
    algorithm: LowCardinality[str]

# create a store by extending the DynaStore class
class RecommendationStore(DynaStore[Recommendation]):
    def save_metadata(self, _metadata: Metadata) -> MetadataId:
        # here you need to handle the saving of the metadata
        # could be in your database, in a file, etc.
        # you need to create and return a unique id for this metadata.
        pass

    def load_metadata(self, _id: MetadataId) -> Metadata:
        # here you need to handle the loading of the metadata from an id
        # could from your database, from a file, etc.
        pass

store = RecommendationStore(Recommendation)

# saving recommendations
id = store.create(Recommendation(userId="user1", timestamp=datetime.now(), algorithm="algo-1"))
# returns a Recommendation id

# loading recommendations
store.parse(id)
# returns a Recommendation object

FAQ

What database does it support?

all. none. You need to handle the storage of the metadata yourself. It could be in a database, in a file, etc.

What about security?

the high cardinality fields are stored in the id, so they are not encrypted. Anyone in possession of this id could:

  • access the high cardinality fields values
  • generate new ids with the different high cardinality fields values

This needs to be taken into account.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dyna_store-0.0.5.tar.gz (5.1 kB view details)

Uploaded Source

Built Distribution

dyna_store-0.0.5-py3-none-any.whl (5.6 kB view details)

Uploaded Python 3

File details

Details for the file dyna_store-0.0.5.tar.gz.

File metadata

  • Download URL: dyna_store-0.0.5.tar.gz
  • Upload date:
  • Size: 5.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for dyna_store-0.0.5.tar.gz
Algorithm Hash digest
SHA256 bbf0e60fd92b63fe65835de4ac685e3daeff6c08284d1afbc7d0d6864fd15f7e
MD5 7574f6f1ea4ce215954a2667eacd1078
BLAKE2b-256 71e6dc8420f7fefc2cfa99360d61bf7a140b7799c0bc2a424fd4f913b3b006c1

See more details on using hashes here.

File details

Details for the file dyna_store-0.0.5-py3-none-any.whl.

File metadata

  • Download URL: dyna_store-0.0.5-py3-none-any.whl
  • Upload date:
  • Size: 5.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for dyna_store-0.0.5-py3-none-any.whl
Algorithm Hash digest
SHA256 40342c383b00f5d861346aa8a09aa1e59349376c9f7bb2048b766e9c7a5a86d3
MD5 89e523438de595648564fdd2075760ea
BLAKE2b-256 02873bd02ef67d0ed99e5c01e8621880564242322cb518f8444605b9f25495c5

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page