diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/OracleDialect.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/OracleDialect.java
index 7f65461093..d995673436 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/OracleDialect.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/OracleDialect.java
@@ -28,7 +28,7 @@
  * An SQL dialect for Oracle.
  *
  * @author Jens Schauder
- * @author Mikahil Polivakha
+ * @author Mikhail Polivakha
  * @since 2.1
  */
 public class OracleDialect extends AnsiDialect {
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java
index 6979c365e9..2bf62bcd76 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/dialect/PostgresDialect.java
@@ -57,6 +57,7 @@ public class PostgresDialect extends AbstractDialect {
 
 	private IdentifierProcessing identifierProcessing = IdentifierProcessing.create(Quoting.ANSI,
 			LetterCasing.LOWER_CASE);
+
 	private IdGeneration idGeneration = new IdGeneration() {
 
 		@Override
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java
index 2b2deff2f2..d727f8f44b 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Criteria.java
@@ -53,6 +53,7 @@
  * @author Oliver Drotbohm
  * @author Roman Chigvintsev
  * @author Jens Schauder
+ * @author Mikhail Polivakha
  * @since 2.0
  */
 public class Criteria implements CriteriaDefinition {
@@ -65,26 +66,32 @@ public class Criteria implements CriteriaDefinition {
 
 	private final @Nullable SqlIdentifier column;
 	private final @Nullable Comparator comparator;
+	private final @Nullable ExtendedComparator extendedComparator;
 	private final @Nullable Object value;
 	private final boolean ignoreCase;
 
-	private Criteria(SqlIdentifier column, Comparator comparator, @Nullable Object value) {
-		this(null, Combinator.INITIAL, Collections.emptyList(), column, comparator, value, false);
+	Criteria(SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value) {
+		this(null, Combinator.INITIAL, Collections.emptyList(), column, comparator, null, value, false);
+	}
+
+	Criteria(SqlIdentifier column, ExtendedComparator extendedComparator, @Nullable Object value) {
+		this(null, Combinator.INITIAL, Collections.emptyList(), column, null, extendedComparator, value, false);
 	}
 
 	private Criteria(@Nullable Criteria previous, Combinator combinator, List<CriteriaDefinition> group,
 			@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value) {
-		this(previous, combinator, group, column, comparator, value, false);
+		this(previous, combinator, group, column, comparator, null, value, false);
 	}
 
 	private Criteria(@Nullable Criteria previous, Combinator combinator, List<CriteriaDefinition> group,
-			@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable Object value, boolean ignoreCase) {
+			@Nullable SqlIdentifier column, @Nullable Comparator comparator, @Nullable ExtendedComparator extendedComparator, @Nullable Object value, boolean ignoreCase) {
 
 		this.previous = previous;
 		this.combinator = previous != null && previous.isEmpty() ? Combinator.INITIAL : combinator;
 		this.group = group;
 		this.column = column;
 		this.comparator = comparator;
+		this.extendedComparator = extendedComparator;
 		this.value = value;
 		this.ignoreCase = ignoreCase;
 	}
@@ -96,6 +103,7 @@ private Criteria(@Nullable Criteria previous, Combinator combinator, List<Criter
 		this.group = group;
 		this.column = null;
 		this.comparator = null;
+		this.extendedComparator = null;
 		this.value = null;
 		this.ignoreCase = false;
 	}
@@ -259,7 +267,7 @@ public Criteria or(List<? extends CriteriaDefinition> criteria) {
 	 */
 	public Criteria ignoreCase(boolean ignoreCase) {
 		if (this.ignoreCase != ignoreCase) {
-			return new Criteria(previous, combinator, group, column, comparator, value, ignoreCase);
+			return new Criteria(previous, combinator, group, column, comparator, extendedComparator, value, ignoreCase);
 		}
 		return this;
 	}
@@ -328,6 +336,7 @@ private boolean doIsEmpty() {
 	/**
 	 * @return {@literal true} if this {@link Criteria} is empty.
 	 */
+	@Override
 	public boolean isGroup() {
 		return !this.group.isEmpty();
 	}
@@ -335,6 +344,7 @@ public boolean isGroup() {
 	/**
 	 * @return {@link Combinator} to combine this criteria with a previous one.
 	 */
+	@Override
 	public Combinator getCombinator() {
 		return combinator;
 	}
@@ -360,6 +370,11 @@ public Comparator getComparator() {
 		return comparator;
 	}
 
+	@Override
+	public ExtendedComparator getExtendedComparator() {
+		return extendedComparator;
+	}
+
 	/**
 	 * @return the comparison value. Can be {@literal null}.
 	 */
@@ -405,12 +420,13 @@ public boolean equals(Object o) {
 				&& Objects.equals(group, criteria.group) //
 				&& Objects.equals(column, criteria.column) //
 				&& comparator == criteria.comparator //
+				&& extendedComparator == criteria.extendedComparator //
 				&& Objects.equals(value, criteria.value);
 	}
 
 	@Override
 	public int hashCode() {
-		return Objects.hash(previous, combinator, group, column, comparator, value, ignoreCase);
+		return Objects.hash(previous, combinator, group, column, comparator, extendedComparator, value, ignoreCase);
 	}
 
 	private void unroll(CriteriaDefinition criteria, StringBuilder stringBuilder) {
@@ -476,29 +492,35 @@ private void render(CriteriaDefinition criteria, StringBuilder stringBuilder) {
 			return;
 		}
 
-		stringBuilder.append(criteria.getColumn().toSql(IdentifierProcessing.NONE)).append(' ')
-				.append(criteria.getComparator().getComparator());
+		stringBuilder.append(criteria.getColumn().toSql(IdentifierProcessing.NONE)).append(' ');
+
+		if (criteria.getExtendedComparator() != null) {
+			stringBuilder.append(criteria.getExtendedComparator().operator()).append(' ').append(renderValue(criteria.getValue()));
+		} else {
 
-		switch (criteria.getComparator()) {
-			case BETWEEN:
-			case NOT_BETWEEN:
-				Pair<Object, Object> pair = (Pair<Object, Object>) criteria.getValue();
-				stringBuilder.append(' ').append(pair.getFirst()).append(" AND ").append(pair.getSecond());
-				break;
+			stringBuilder.append(criteria.getComparator().getComparator());
 
-			case IS_NULL:
-			case IS_NOT_NULL:
-			case IS_TRUE:
-			case IS_FALSE:
-				break;
+			switch (criteria.getComparator()) {
+				case BETWEEN:
+				case NOT_BETWEEN:
+					Pair<Object, Object> pair = (Pair<Object, Object>) criteria.getValue();
+					stringBuilder.append(' ').append(pair.getFirst()).append(" AND ").append(pair.getSecond());
+					break;
 
-			case IN:
-			case NOT_IN:
-				stringBuilder.append(" (").append(renderValue(criteria.getValue())).append(')');
-				break;
+				case IS_NULL:
+				case IS_NOT_NULL:
+				case IS_TRUE:
+				case IS_FALSE:
+					break;
 
-			default:
-				stringBuilder.append(' ').append(renderValue(criteria.getValue()));
+				case IN:
+				case NOT_IN:
+					stringBuilder.append(" (").append(renderValue(criteria.getValue())).append(')');
+					break;
+
+				default:
+					stringBuilder.append(' ').append(renderValue(criteria.getValue()));
+			}
 		}
 	}
 
@@ -515,6 +537,10 @@ private static String renderValue(@Nullable Object value) {
 			return joiner.toString();
 		}
 
+		if (value instanceof CriteriaLiteral literal) {
+			return literal.getLiteral();
+		}
+
 		if (value != null) {
 			return String.format("'%s'", value);
 		}
@@ -653,6 +679,12 @@ public interface CriteriaStep {
 		 * @return a new {@link Criteria} object
 		 */
 		Criteria isFalse();
+
+	}
+
+	static interface CriteriaLiteral {
+
+		String getLiteral();
 	}
 
 	/**
@@ -812,7 +844,7 @@ public Criteria isFalse() {
 			return createCriteria(Comparator.IS_FALSE, false);
 		}
 
-		protected Criteria createCriteria(Comparator comparator, @Nullable Object value) {
+        protected Criteria createCriteria(@Nullable Comparator comparator, @Nullable Object value) {
 			return new Criteria(this.property, comparator, value);
 		}
 	}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/CriteriaDefinition.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/CriteriaDefinition.java
index c09129a1b6..941469bb3d 100644
--- a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/CriteriaDefinition.java
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/CriteriaDefinition.java
@@ -28,6 +28,7 @@
  *
  * @author Mark Paluch
  * @author Jens Schauder
+ * @author Mikhail Polivakha
  * @since 2.0
  */
 public interface CriteriaDefinition {
@@ -97,6 +98,12 @@ static CriteriaDefinition from(List<? extends CriteriaDefinition> criteria) {
 	@Nullable
 	Comparator getComparator();
 
+	/**
+	 * @return {@link ExtendedComparator}.
+	 */
+	@Nullable
+	ExtendedComparator getExtendedComparator();
+
 	/**
 	 * @return the comparison value. Can be {@literal null}.
 	 */
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/ExtendedComparator.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/ExtendedComparator.java
new file mode 100644
index 0000000000..32039d0494
--- /dev/null
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/ExtendedComparator.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.relational.core.query;
+
+/**
+ * Analog of {@link org.springframework.data.relational.core.query.CriteriaDefinition.Comparator} for the extended operators,
+ * that are not commonly supported by RDBMS vendors.
+ *
+ * @author Mikhail Polivakha
+ */
+interface ExtendedComparator {
+
+	String operator();
+
+	/**
+	 * PostgreSQL specific operator for checking if the SQL ARRAY contains the given sub-array.
+	 *
+	 * @author Mikhail Polivakha
+	 */
+	enum PostgresExtendedContains implements ExtendedComparator {
+
+		INSTANCE;
+
+		@Override
+		public String operator() {
+			return "@>";
+		}
+	}
+}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/OngoingArrayCriteria.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/OngoingArrayCriteria.java
new file mode 100644
index 0000000000..4a765fe2b4
--- /dev/null
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/OngoingArrayCriteria.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2020-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.relational.core.query;
+
+/**
+ * An Ongoing Criteria builder for {@link java.sql.Types#ARRAY SQL Array} related operations.
+ * Used by intermediate builder objects returned from the {@link Criteria}.
+ *
+ * @author Mikhail Polivakha
+ */
+public interface OngoingArrayCriteria {
+
+	/**
+	 * Builds a {@link Criteria} where the pre-defined array must contain given values.
+	 *
+	 * @param values values to be present in the array
+	 * @return built {@link Criteria}
+	 */
+	Criteria contains(Object... values);
+}
diff --git a/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Postgres.java b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Postgres.java
new file mode 100644
index 0000000000..82d56abb0c
--- /dev/null
+++ b/spring-data-relational/src/main/java/org/springframework/data/relational/core/query/Postgres.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020-2025 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.relational.core.query;
+
+import static org.springframework.data.relational.core.query.Criteria.CriteriaLiteral;
+
+import java.sql.JDBCType;
+import java.util.StringJoiner;
+
+import org.jetbrains.annotations.NotNull;
+import org.springframework.data.relational.core.sql.SqlIdentifier;
+import org.springframework.util.Assert;
+
+/**
+ * PostgreSQL-specific {@link Criteria} conditions.
+ *
+ * @author Mikhail Polivakha
+ */
+public class Postgres {
+
+	/**
+	 * Custom {@link Criteria} condition builder to check if the column of an {@link java.sql.Types#ARRAY ARRAY} sql type
+	 * matches specific conditions. Samples of usage is:
+	 * <p>
+	 * <pre class="code">
+	 * // Code below produces the SQL: "my_column" @> ARRAY['A', 'B']
+	 * Postgres.whereArray("my_column").contains("A", "B")
+	 * </pre>
+	 * Code above produces the SQL:
+	 * <pre class="code">
+	 *   "my_column" @> ARRAY['A', 'B']
+	 * </pre>
+	 *
+	 * @param arrayName the name of an ARRAY column to match against
+	 * @return the {@link OngoingArrayCriteria} to chain future condition
+	 */
+	public static OngoingArrayCriteria array(String arrayName) {
+		return new PostgresCriteriaArray(arrayName);
+	}
+
+	public static class PostgresCriteriaArray implements OngoingArrayCriteria {
+
+		private final String arrayColumnName;
+
+		public PostgresCriteriaArray(String arrayColumnName) {
+			this.arrayColumnName = arrayColumnName;
+		}
+
+		@NotNull
+		@Override
+		public Criteria
+		contains(Object... values) {
+			Assert.notNull(values, "values array cannot be null");
+
+			return new Criteria(SqlIdentifier.quoted(arrayColumnName), ExtendedComparator.PostgresExtendedContains.INSTANCE, new CriteriaLiteral() {
+
+				@Override
+				public String getLiteral() {
+					boolean quoted = true;
+
+					if (values.length > 0) {
+						quoted = !Number.class.isAssignableFrom(values[0].getClass());
+					}
+
+					return toArrayLiteral(quoted, values);
+				}
+			});
+		}
+
+		@SafeVarargs
+		public final <T> String toArrayLiteral(boolean quoted, T... values) {
+			StringJoiner accumulator = new StringJoiner(",", "ARRAY[", "]");
+
+			for (T value : values) {
+				if (value != null) {
+					if (quoted) {
+						accumulator.add("'" + value + "'");
+					} else {
+						accumulator.add(value.toString());
+					}
+				} else {
+					accumulator.add(JDBCType.NULL.name());
+				}
+			}
+			return accumulator.toString();
+		}
+	}
+}
diff --git a/spring-data-relational/src/test/java/org/springframework/data/relational/core/query/CriteriaUnitTests.java b/spring-data-relational/src/test/java/org/springframework/data/relational/core/query/CriteriaUnitTests.java
index d107c67e72..57888cfc07 100644
--- a/spring-data-relational/src/test/java/org/springframework/data/relational/core/query/CriteriaUnitTests.java
+++ b/spring-data-relational/src/test/java/org/springframework/data/relational/core/query/CriteriaUnitTests.java
@@ -21,6 +21,7 @@
 
 import java.util.Arrays;
 
+import org.assertj.core.api.InstanceOfAssertFactories;
 import org.junit.jupiter.api.Test;
 import org.springframework.data.relational.core.sql.SqlIdentifier;
 
@@ -30,6 +31,7 @@
  * @author Mark Paluch
  * @author Jens Schauder
  * @author Roman Chigvintsev
+ * @author Mikhail Polivakha
  */
 class CriteriaUnitTests {
 
@@ -95,6 +97,27 @@ void andChainedCriteria() {
 		assertThat(criteria.getValue()).isEqualTo("bar");
 	}
 
+	@Test // DATAJDBC-513
+	void andChainedCriteriaWithDialectCriteriaCondition() {
+
+		Criteria criteria = where("foo").is("bar").and(Postgres.array("baz").contains("first", "second"));
+		var previous = criteria.getPrevious();
+
+		assertSoftly(softAssertions -> {
+			softAssertions.assertThat(criteria.getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.quoted("baz"));
+			softAssertions.assertThat(criteria.getComparator()).isNull();
+			softAssertions.assertThat(criteria.getValue()).isNull();
+			softAssertions.assertThat(criteria.getPrevious()).isNotNull();
+			softAssertions.assertThat(criteria.getCombinator()).isEqualTo(Criteria.Combinator.AND);
+			softAssertions.assertThat(criteria.toString()).isEqualTo("foo = 'bar' AND (baz @> ARRAY['first','second'])");
+
+			softAssertions.assertThat(previous.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
+			softAssertions.assertThat(previous.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
+			softAssertions.assertThat(previous.getValue()).isEqualTo("bar");
+			softAssertions.assertThat(previous.toString()).isEqualTo("foo = 'bar'");
+		});
+	}
+
 	@Test // DATAJDBC-513
 	void andGroupedCriteria() {
 
@@ -116,6 +139,26 @@ void andGroupedCriteria() {
 		assertThat(grouped).hasToString("foo = 'bar' AND (foo = 'baz' OR bar IS NOT NULL)");
 	}
 
+	@Test // DATAJDBC-1953
+	void andGroupedCriteriaWithDialectCriteriaCondition() {
+
+		Criteria grouped = where("foo").is("bar").and(where("foo").is("baz").or(Postgres.array("bar").contains("electronics")));
+		Criteria previous = grouped.getPrevious();
+
+		assertSoftly(softAssertions -> {
+			softAssertions.assertThat(grouped.isGroup()).isTrue();
+			softAssertions.assertThat(grouped.getGroup()).hasSize(1);
+			softAssertions.assertThat(grouped.getGroup().get(0).getGroup().get(0).getColumn()).isEqualTo(SqlIdentifier.unquoted("\"bar\""));
+			softAssertions.assertThat(grouped.getCombinator()).isEqualTo(Criteria.Combinator.AND);
+			softAssertions.assertThat(grouped).hasToString("foo = 'bar' AND (foo = 'baz' OR (bar @> ARRAY['electronics']))");
+
+			softAssertions.assertThat(previous).isNotNull();
+			softAssertions.assertThat(previous.getColumn()).isEqualTo(SqlIdentifier.unquoted("foo"));
+			softAssertions.assertThat(previous.getComparator()).isEqualTo(CriteriaDefinition.Comparator.EQ);
+			softAssertions.assertThat(previous.getValue()).isEqualTo("bar");
+		});
+	}
+
 	@Test // DATAJDBC-513
 	void orChainedCriteria() {
 
@@ -179,6 +222,25 @@ void shouldBuildNotEqualsCriteria() {
 		assertThat(criteria.getValue()).isEqualTo("bar");
 	}
 
+	@Test // DATAJDBC-1953
+	void shouldBuildSimplePredefinedDialectCriteriaCondition() {
+
+		Object[] values = { 1, 2, 3 };
+		Criteria criteria = Postgres.array("foo").contains(values);
+
+		assertSoftly(softAssertions -> {
+			softAssertions.assertThat(criteria.getColumn()).isEqualTo(SqlIdentifier.quoted("foo"));
+			softAssertions.assertThat(criteria.getComparator()).isNull();
+			softAssertions.assertThat(criteria.getValue()).isInstanceOf(CriteriaLiteral.class);
+			softAssertions
+					.assertThat(criteria.getValue())
+					.asInstanceOf(InstanceOfAssertFactories.type(CriteriaLiteral.class))
+					.extracting(CriteriaLiteral::getLiteral)
+					.isEqualTo("ARRAY[1,2,3]");
+			softAssertions.assertThat(criteria.toString()).isEqualTo("foo @> ARRAY[1,2,3]");
+		});
+	}
+
 	@Test // DATAJDBC-513
 	void shouldBuildInCriteria() {