Skip to main content

tickets_tags

Free-text tags applied to a ticket. One row per (ticket, tag). Used for ad-hoc categorization that does not fit the closed status enum or progress-label semantics.

Source Mapping

CouchDB document type: a "ticket" document — rows are produced by asyncconvert.py's tickets_tags(obj) handler iterating the ticket's tags[] array. Each element becomes one row.

ColumnCouchDB sourceNotes
tagtags[i]One element of the ticket's tags array, cast to a string. Free text.
ticketididThe tickets.id this row belongs to.
projectiddatabaseThe project this ticket belongs to.
couchdbidcouchDbIdLegacy CouchDB document identifier (the ticket's).

Column Reference

ColumnTypeNullableDescription
tagVARCHAR(255)yesFree-text tag value applied to the ticket.
ticketidVARCHAR(255)yesForeign-key reference to tickets.id.
projectidVARCHAR(255)yesThe project this ticket belongs to.
couchdbidVARCHAR(255)yesLegacy CouchDB identifier of the ticket document.

Keys

  • No primary key. Identity is the unique constraint uk_ticket_tag on (ticketid, tag).
  • Unique key: uk_ticket_tag on (ticketid, tag).

Indexes

  • idx_projectid on projectid
  • idx_ticket on ticketid

Relationships

DirectionOther tableJoinCardinality
outgoingticketstickets_tags.ticketid = tickets.idmany rows → one ticket
outgoingprojectstickets_tags.projectid = projects.idmany rows → one project

None of these are foreign-keyed in MariaDB; joins are by string match.

Refresh Semantics

tickets_tags is rebuilt per ticket document. On each observation of a ticket, the converter:

  1. Issues DELETE FROM tickets_tags WHERE ticketid = <ticket_id> (when delete tracking is enabled).
  2. Iterates the ticket's tags[] array and emits one INSERT IGNORE per element.

Inserts are INSERT IGNORE against the (ticketid, tag) unique key, so duplicate tags within a single source document collapse.

A reindex with type=ticket (or a full reindex) rebuilds this table as part of the ticket reindex.

Common Queries

All tags on a ticket

SELECT tag
FROM tickets_tags
WHERE ticketid = 'your_ticket_id'
ORDER BY tag;

Ticket count per tag (project scoped)

SELECT
tag,
COUNT(DISTINCT ticketid) AS tickets
FROM tickets_tags
WHERE projectid = 'your_project_id'
GROUP BY tag
ORDER BY tickets DESC;

Tickets carrying a specific tag

SELECT t.id, t.title, t.status, t.dueDate
FROM tickets t
JOIN tickets_tags tt ON tt.ticketid = t.id
WHERE tt.tag = 'urgent'
AND t.archived IS NULL
ORDER BY t.dueDate;

Pitfalls

  • tag is free text. Casing and spelling drift across users. Group with LOWER(tag) if cross-user rollups matter.
  • No primary key. Identity is (ticketid, tag) — a tag appears at most once per ticket, but the same string can apply to many tickets.
  • Reading during an in-flight reindex of a ticket may briefly return zero rows for that ticket. Between the DELETE and the INSERTs, WHERE ticketid = <id> returns nothing.
  • No FK constraints. Joins to tickets.id are by string match.