We're designing a system to define user groups. The groups will be used to run queries, to target promotions at relevant users. For example, to send a "$5 Free if you come back this week" offer to users who haven't shopped at a particular merchant in a while.
A group is defined by a set of filters, of which there are many. For example:
- Has made a purchase within the last 30 days
- Has shopped at merchant X
- Total spent greater than $50
We can expect new filters to be added regularly, as the needs of the marketing department change.
A user group has a name, and an associated set of filters. For example:
const lapsedMcDonaldsUsers = UserGroup({
name: "Big McDonalds spenders who've lapsed",
filters: [
TotalSpent({greaterThan: 100.00, atMerchant: MCDONALDS_ID}),
DaysSinceLastPurchase({greaterThan: 30, atMerchant: MCDONALDS_ID})
]
})
Someone from the marketing department will define the groups and their filters using a web interface. That definition will be stored in a database. They'll then be able to schedule emails to be sent to the user groups. At send time, a query based on the filters will run to generate the list of recipients.
The question is how best to define the database schema to store the user groups and filters. Here's my first attempt:
UserGroups
----------
id: primary_key
name: string
Filters
-------
id: primary_key
TotalSpentFilters
-----------------
id: primary_key
filter_id: foreign_key
merchant_id: foreign_key
total_spent: integer
DaysSinceLastPurchaseFilters
----------------------------
id: primary_key
filter_id: foreign_key
merchant_id: foreign_key
days_since: integer
.... (many more)
UserGroupFiltersBindery
-----------------------
id: primary_key
user_group_id: foreign_key
filter_id: foreign_key
So I'm using a table inheritance pattern, where each individual filter is defined in its own table, which points to a record in the general Filters
table. The UserGroupFiltersBindery
is then responsible for linking together a UserGroup
and its Filters
.
Thoughts on this design? Ideas from improvements? Possible problems?