Selecto.Builder.Sql.Tagging (Selecto v0.3.16)

Many-to-many tagging SQL pattern generation for join table relationships.

Supports tagging patterns through intermediate join tables with aggregation and faceted filtering capabilities. Handles the complexity of many-to-many relationships while maintaining proper parameterization.

Phase 3: Full many-to-many implementation with tag aggregation and faceted filtering

supported-patterns

Supported Patterns

  • Basic many-to-many joins: LEFT JOIN through intermediate table
  • Tag aggregation: string_agg for comma-separated tag lists
  • Faceted filtering: EXISTS subqueries for tag filtering
  • Tag counting: COUNT-based filtering for minimum tag requirements

examples

Examples

# Basic tagging join: posts ↔ post_tags ↔ tags
config = %{
  source: "tags",
  join_table: "post_tags",  
  tag_field: "name",
  main_foreign_key: "post_id",
  tag_foreign_key: "tag_id"
}

# Generates SQL like:
# LEFT JOIN post_tags pt ON main.id = pt.post_id  
# LEFT JOIN tags t ON pt.tag_id = t.id
# With string_agg(t.name, ', ') for aggregation

Link to this section Summary

Functions

Build faceted tag filter using EXISTS subquery.

Build tag count filter for minimum tag requirements.

Build many-to-many tagging join with intermediate table.

Link to this section Functions

Link to this function

build_faceted_tag_filter(config, tag_values, match_type \\ :any)

Build faceted tag filter using EXISTS subquery.

Generates EXISTS subqueries for filtering records that have specific tags. Supports both single tag and array-based tag filtering.

examples

Examples

# Single tag filter
build_faceted_tag_filter(config, "programming", :single)

# Multiple tags filter (ANY match)
build_faceted_tag_filter(config, ["elixir", "phoenix"], :any)

# Multiple tags filter (ALL required)  
build_faceted_tag_filter(config, ["web", "backend"], :all)

Returns: {where_clause_iodata, params}

Link to this function

build_tag_aggregation_column(tag_table_alias, tag_field, column_alias)

Build tag aggregation column SQL.

Generates string_agg expressions for displaying comma-separated tag lists. Handles NULL values and provides proper GROUP BY compatibility.

examples

Examples

build_tag_aggregation_column("tags", "name", "tag_list")
#=> "string_agg(tags.name, ', ') as tag_list"

build_tag_aggregation_column("categories", "title", "category_names")  
#=> "string_agg(categories.title, ', ') as category_names"

Returns: iodata for SELECT clause

Link to this function

build_tag_count_column(tag_table_alias, column_alias)

Build tag count column SQL.

Generates COUNT expressions for counting distinct tags per record. Useful for filtering by minimum tag requirements.

examples

Examples

build_tag_count_column("tags", "tag_count")
#=> "COUNT(DISTINCT tags.id) as tag_count"

Returns: iodata for SELECT clause

Link to this function

build_tag_count_filter(config, arg)

Build tag count filter for minimum tag requirements.

Generates WHERE conditions that filter records based on the number of tags they have. Useful for finding "well-tagged" content.

examples

Examples

build_tag_count_filter(config, {:gte, 3})  # At least 3 tags
build_tag_count_filter(config, {:eq, 1})   # Exactly 1 tag  
build_tag_count_filter(config, {:between, 2, 5})  # Between 2-5 tags

Returns: {where_clause_iodata, params}

Link to this function

build_tagging_join_with_aggregation(selecto, join, config, fc, p, ctes)

Build many-to-many tagging join with intermediate table.

Generates the double-JOIN pattern required for many-to-many relationships:

  1. Main table → intermediate join table
  2. Join table → tag table

Includes support for tag aggregation and proper GROUP BY handling.

parameters

Parameters

  • selecto: Main selecto struct
  • join: Join identifier (atom)
  • config: Join configuration with tagging options
  • fc: Current from clause iodata
  • p: Current parameters list
  • ctes: Current CTEs list

Returns: {updated_from_clause, updated_params, updated_ctes}