diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
index df8336285..502aeb408 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
@@ -56,6 +56,7 @@ import com.mongodb.BasicDBList;
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mark Paluch
+ * @author Andreas Zink
*/
public class Criteria implements CriteriaDefinition {
@@ -663,6 +664,118 @@ public class Criteria implements CriteriaDefinition {
BasicDBList bsonList = createCriteriaList(criteria);
return registerCriteriaChainElement(new Criteria("$and").is(bsonList));
}
+
+ /**
+ * Creates a criterion using the {@literal $bitsAllClear} operator.
+ *
+ * @param numericBitmask non-negative numeric bitmask
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAllClear
+ * @since 2.1
+ */
+ public Criteria bitsAllClear(int numericBitmask) {
+ criteria.put("$bitsAllClear", Integer.valueOf(numericBitmask));
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAllClear} operator.
+ *
+ * @param bitPositions positions of set bits
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAllClear
+ * @since 2.1
+ */
+ public Criteria bitsAllClear(Collection bitPositions) {
+ criteria.put("$bitsAllClear", bitPositions);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAllSet} operator.
+ *
+ * @param numericBitmask non-negative numeric bitmask
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAllSet
+ * @since 2.1
+ */
+ public Criteria bitsAllSet(int numericBitmask) {
+ criteria.put("$bitsAllSet", Integer.valueOf(numericBitmask));
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAllSet} operator.
+ *
+ * @param bitPositions positions of set bits
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAllSet
+ * @since 2.1
+ */
+ public Criteria bitsAllSet(Collection bitPositions) {
+ criteria.put("$bitsAllSet", bitPositions);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAnyClear} operator.
+ *
+ * @param numericBitmask non-negative numeric bitmask
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAnyClear
+ * @since 2.1
+ */
+ public Criteria bitsAnyClear(int numericBitmask) {
+ criteria.put("$bitsAnyClear", Integer.valueOf(numericBitmask));
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAnyClear} operator.
+ *
+ * @param bitPositions positions of set bits
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAnyClear
+ * @since 2.1
+ */
+ public Criteria bitsAnyClear(Collection bitPositions) {
+ criteria.put("$bitsAnyClear", bitPositions);
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAnySet} operator.
+ *
+ * @param numericBitmask non-negative numeric bitmask
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAnySet
+ * @since 2.1
+ */
+ public Criteria bitsAnySet(int numericBitmask) {
+ criteria.put("$bitsAnySet", Integer.valueOf(numericBitmask));
+ return this;
+ }
+
+ /**
+ * Creates a criterion using the {@literal $bitsAnySet} operator.
+ *
+ * @param bitPositions positions of set bits
+ * @return
+ * @see MongoDB Query operator:
+ * $bitsAnySet
+ * @since 2.1
+ */
+ public Criteria bitsAnySet(Collection bitPositions) {
+ criteria.put("$bitsAnySet", bitPositions);
+ return this;
+ }
private Criteria registerCriteriaChainElement(Criteria criteria) {
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
index 9aa7990b5..eab9e1d50 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java
@@ -3361,6 +3361,61 @@ public class MongoTemplateTests {
assertThat(template.count(query(where("field").is("stark")), Sample.class)).isEqualTo(0L);
}
+ @Test // DATAMONGO-1808
+ public void testFindByBitmasks() {
+ DocumentWithBitmask document = new DocumentWithBitmask(0b101);
+ template.insert(document);
+
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAllClear(0b010)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAllClear(Arrays.asList(1))),
+ DocumentWithBitmask.class)).hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAllClear(0b010)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAllClear(Arrays.asList(1))),
+ DocumentWithBitmask.class)).hasSize(1);
+
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAllSet(0b101)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAllSet(Arrays.asList(0, 2))),
+ DocumentWithBitmask.class)).hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAllSet(0b101)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAllSet(Arrays.asList(0, 2))),
+ DocumentWithBitmask.class)).hasSize(1);
+
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAnyClear(0b111)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAnyClear(Arrays.asList(0, 1, 2))),
+ DocumentWithBitmask.class)).hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAnyClear(0b111)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAnyClear(Arrays.asList(0, 1, 2))),
+ DocumentWithBitmask.class)).hasSize(1);
+
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAnySet(0b111)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("intValue").bitsAnySet(Arrays.asList(0, 1, 2))),
+ DocumentWithBitmask.class)).hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAnySet(0b111)), DocumentWithBitmask.class))
+ .hasSize(1);
+ assertThat(template.find(Query.query(Criteria.where("binaryValue").bitsAnySet(Arrays.asList(0, 1, 2))),
+ DocumentWithBitmask.class)).hasSize(1);
+ }
+
+ @NoArgsConstructor
+ static class DocumentWithBitmask {
+ @Id String id;
+ int intValue;
+ byte[] binaryValue;
+
+ public DocumentWithBitmask(int value) {
+ this.intValue = value;
+ this.binaryValue = new byte[] { (byte) value };
+ }
+
+ }
+
static class TypeWithNumbers {
@Id String id;
diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java
index 542911261..1bbcd28fb 100644
--- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java
+++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java
@@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
+import java.util.Arrays;
import java.util.Collections;
import org.bson.Document;
@@ -236,4 +237,46 @@ public class CriteriaTests {
assertThat(critera.getCriteriaObject(), is(equalTo(new Document("$jsonSchema",
new Document("type", "object").append("required", Collections.singletonList("name"))))));
}
+
+ @Test // DATAMONGO-1808
+ public void testBitsAllClear() {
+ Criteria numericBitmaskCriteria = new Criteria("field").bitsAllClear(0b101);
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAllClear\" : 5} }"),
+ numericBitmaskCriteria.getCriteriaObject());
+
+ Criteria bitPositionsBitmaskCriteria = new Criteria("field").bitsAllClear(Arrays.asList(0, 2));
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAllClear\" : [ 0, 2 ]} }"),
+ bitPositionsBitmaskCriteria.getCriteriaObject());
+ }
+
+ @Test // DATAMONGO-1808
+ public void testBitsAllSet() {
+ Criteria numericBitmaskCriteria = new Criteria("field").bitsAllSet(0b101);
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAllSet\" : 5} }"), numericBitmaskCriteria.getCriteriaObject());
+
+ Criteria bitPositionsBitmaskCriteria = new Criteria("field").bitsAllSet(Arrays.asList(0, 2));
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAllSet\" : [ 0, 2 ]} }"),
+ bitPositionsBitmaskCriteria.getCriteriaObject());
+ }
+
+ @Test // DATAMONGO-1808
+ public void testBitsAnyClear() {
+ Criteria numericBitmaskCriteria = new Criteria("field").bitsAnyClear(0b101);
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAnyClear\" : 5} }"),
+ numericBitmaskCriteria.getCriteriaObject());
+
+ Criteria bitPositionsBitmaskCriteria = new Criteria("field").bitsAnyClear(Arrays.asList(0, 2));
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAnyClear\" : [ 0, 2 ]} }"),
+ bitPositionsBitmaskCriteria.getCriteriaObject());
+ }
+
+ @Test // DATAMONGO-1808
+ public void testBitsAnySet() {
+ Criteria numericBitmaskCriteria = new Criteria("field").bitsAnySet(0b101);
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAnySet\" : 5} }"), numericBitmaskCriteria.getCriteriaObject());
+
+ Criteria bitPositionsBitmaskCriteria = new Criteria("field").bitsAnySet(Arrays.asList(0, 2));
+ assertEquals(Document.parse("{ \"field\" : { \"$bitsAnySet\" : [ 0, 2 ]} }"),
+ bitPositionsBitmaskCriteria.getCriteriaObject());
+ }
}