Text and pattern functions and operators

This page covers PostgreSQL text processing, pattern matching, and regular expression functions and operators available in this library.

See also: Examples for these functions in whole queries

Text and pattern operators

Some PostgreSQL operators have multiple meanings depending on the data types involved. This library provides specific DQL function names to avoid conflicts:

Operator Array/JSON usage Spatial usage Text/pattern usage
~ N/A SPATIAL_CONTAINS (bounding box contains) REGEXP (text pattern matching)

Usage Guidelines:

  • Text: Use REGEXP, IREGEXP for pattern matching
  • Boolean operators: All operators return boolean values and should be used with = TRUE or = FALSE in DQL (see Writing DQL)

Text and pattern operators

PostgreSQL operator Register for DQL as Implemented by
ilike ILIKE (Usage note) MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ilike
similar to SIMILAR_TO MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SimilarTo
not similar to NOT_SIMILAR_TO MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotSimilarTo
~ REGEXP MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Regexp
~* IREGEXP MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IRegexp
!~ NOT_REGEXP MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotRegexp
!~* NOT_IREGEXP MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotIRegexp
@@ TSMATCH MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Tsmatch
|| STRCONCAT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StrConcat

Regular expression functions

PostgreSQL functions Register for DQL as Implemented by
regexp_count REGEXP_COUNT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpCount
regexp_instr REGEXP_INSTR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpInstr
regexp_like REGEXP_LIKE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike
regexp_match REGEXP_MATCH MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpMatch
regexp_split_to_array REGEXP_SPLIT_TO_ARRAY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSplitToArray
regexp_replace REGEXP_REPLACE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpReplace
regexp_substr REGEXP_SUBSTR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr

Text processing functions

PostgreSQL functions Register for DQL as Implemented by
ascii ASCII MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ascii
btrim BTRIM MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Btrim
casefold CASEFOLD MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Casefold
char_length CHAR_LENGTH MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\CharLength
chr CHR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Chr
concat_ws CONCAT_WS MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ConcatWs
decode DECODE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Decode
encode ENCODE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Encode
format FORMAT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Format
initcap INITCAP MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Initcap
left LEFT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Left
lpad LPAD MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Lpad
ltrim LTRIM MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Ltrim
octet_length OCTET_LENGTH MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\OctetLength
quote_ident QUOTE_IDENT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\QuoteIdent
quote_literal QUOTE_LITERAL MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\QuoteLiteral
quote_nullable QUOTE_NULLABLE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\QuoteNullable
repeat REPEAT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Repeat
reverse REVERSE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Reverse
right RIGHT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Right
rpad RPAD MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Rpad
rtrim RTRIM MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Rtrim
split_part SPLIT_PART MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\SplitPart
starts_with STARTS_WITH MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StartsWith
strpos STRPOS MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Strpos
string_agg STRING_AGG MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StringAgg
string_to_array STRING_TO_ARRAY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\StringToArray
translate TRANSLATE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Translate
unaccent UNACCENT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Unaccent

Full-text search functions

PostgreSQL functions Register for DQL as Implemented by
array_to_tsvector ARRAY_TO_TSVECTOR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ArrayToTsvector
json_to_tsvector JSON_TO_TSVECTOR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\JsonToTsvector
phraseto_tsquery PHRASETO_TSQUERY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PhrasetoTsquery
plainto_tsquery PLAINTO_TSQUERY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\PlaintoTsquery
setweight SETWEIGHT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Setweight
strip STRIP MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Strip
to_tsquery TO_TSQUERY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsquery
to_tsvector TO_TSVECTOR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTsvector
ts_headline TS_HEADLINE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsHeadline
ts_rank TS_RANK MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsRank
ts_rank_cd TS_RANK_CD MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsRankCd
tsquery_phrase TSQUERY_PHRASE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsqueryPhrase
tsvector_to_array TSVECTOR_TO_ARRAY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\TsvectorToArray
websearch_to_tsquery WEBSEARCH_TO_TSQUERY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\WebsearchToTsquery

Fuzzy string matching functions (fuzzystrmatch extension)

Requires the fuzzystrmatch extension: CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;

PostgreSQL functions Register for DQL as Implemented by
daitch_mokotoff DAITCH_MOKOTOFF MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\DaitchMokotoff
difference DIFFERENCE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Difference
dmetaphone DMETAPHONE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Dmetaphone
dmetaphone_alt DMETAPHONE_ALT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\DmetaphoneAlt
levenshtein LEVENSHTEIN MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Levenshtein
levenshtein_less_equal LEVENSHTEIN_LESS_EQUAL MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\LevenshteinLessEqual
metaphone METAPHONE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Metaphone
soundex SOUNDEX MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Fuzzystrmatch\Soundex

Trigram similarity functions (pg_trgm extension)

Requires the pg_trgm extension: CREATE EXTENSION IF NOT EXISTS pg_trgm;

Similarity functions

PostgreSQL function Register for DQL as Implemented by
similarity SIMILARITY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\Similarity
word_similarity WORD_SIMILARITY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\WordSimilarity
strict_word_similarity STRICT_WORD_SIMILARITY MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\StrictWordSimilarity

Similarity threshold operators

PostgreSQL operator Register for DQL as Implemented by
% ARE_SIMILAR MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\AreSimilar
<% IS_WORD_SIMILAR_TO MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\IsWordSimilarTo
%> CONTAINS_WORD_SIMILAR_TO MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ContainsWordSimilarTo
«% IS_STRICT_WORD_SIMILAR_TO MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\IsStrictWordSimilarTo
%» CONTAINS_STRICT_WORD_SIMILAR_TO MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ContainsStrictWordSimilarTo

Distance operators

PostgreSQL operator Register for DQL as Implemented by
<-> SIMILARITY_DISTANCE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\SimilarityDistance
«-> WORD_SIMILARITY_DISTANCE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\WordSimilarityDistance
<-» REVERSE_WORD_SIMILARITY_DISTANCE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ReverseWordSimilarityDistance
«<-> STRICT_WORD_SIMILARITY_DISTANCE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\StrictWordSimilarityDistance
<-»> REVERSE_STRICT_WORD_SIMILARITY_DISTANCE MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Trgm\ReverseStrictWordSimilarityDistance

Hashing and checksum functions

PostgreSQL functions Register for DQL as Implemented by
bit_count BIT_COUNT MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BitCount
crc32 CRC32 MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Crc32
crc32c CRC32C MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Crc32c
md5 MD5 MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Md5
reverse (bytea) REVERSE_BYTES MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ReverseBytes
sha224 SHA224 MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha224
sha256 SHA256 MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha256
sha384 SHA384 MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha384
sha512 SHA512 MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Sha512

BIT_COUNT takes a bytea or a bit string. PostgreSQL cannot tell which a bare string literal is, so give it a type, as in BIT_COUNT(DECODE('ff', 'hex')).

Usage examples

The results come from these rows of Entity:

id email text content category name
1 ada@example.com Released on 2026-09-27 The search engine ranks the search terms books Dune
2 not-an-email No date here A search for other terms books Neuromancer
3 miles@jazz.example.org Recorded 1959-03-02 Nothing relevant music Kind of Blue

Each -- → line under a query is one row of its result. A query without its own ORDER BY has its rows listed in sample-row order, or by group.

-- REGEXP_LIKE with a real-world email pattern - POSIX syntax, not SQL LIKE syntax
SELECT e FROM Entity e WHERE REGEXP_LIKE(e.email, '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$') = TRUE
-- → Entity {id: 1}
--   Entity {id: 3}

-- REGEXP_MATCH returns an array of capture groups (one element per group)
SELECT REGEXP_MATCH(e.text, '([0-9]{4})-([0-9]{2})-([0-9]{2})') as date_parts FROM Entity e
-- → ['date_parts' => '{2026,09,27}']
--   ['date_parts' => null]
--   ['date_parts' => '{1959,03,02}']

-- Full-text search: combine TO_TSVECTOR + TO_TSQUERY; must use = TRUE in DQL WHERE clauses
SELECT e FROM Entity e WHERE TSMATCH(TO_TSVECTOR(e.content), TO_TSQUERY('search & terms')) = TRUE
-- → Entity {id: 1}
--   Entity {id: 2}

-- TS_RANK: sort by relevance score - smaller values are less relevant
SELECT e, TS_RANK(TO_TSVECTOR(e.content), TO_TSQUERY('search')) as rank FROM Entity e ORDER BY rank DESC
-- → [0 => Entity {id: 1}, 'rank' => 0.075990885]
--   [0 => Entity {id: 2}, 'rank' => 0.06079271]
--   [0 => Entity {id: 3}, 'rank' => 0.0]

-- STRING_AGG with separator - requires GROUP BY
SELECT e.category, STRING_AGG(e.name, ', ' ORDER BY e.name) as names FROM Entity e GROUP BY e.category
-- → ['category' => 'books', 'names' => 'Dune, Neuromancer']
--   ['category' => 'music', 'names' => 'Kind of Blue']

Tips:

  • REGEXP, IREGEXP and the REGEXP_* functions take POSIX regular expressions, not LIKE patterns.
  • ILIKE is LIKE without case sensitivity.
  • Full-text search stays fast on large tables with a GIN index on the tsvector.
  • UNACCENT requires the unaccent extension: CREATE EXTENSION IF NOT EXISTS unaccent;
  • STRING_AGG takes the separator as its second argument and an ORDER BY inside the call.