DATAMONGO-1808 - Add support for bitwise query operators.

Add support for $bitsAllClear, $bitsAllSet, $bitsAnyClear and $bitsAnySet.

Original Pull Request: #507
This commit is contained in:
Andreas Zink
2017-10-21 16:47:23 +02:00
committed by Christoph Strobl
parent c2516946e9
commit ef872d2527
3 changed files with 211 additions and 0 deletions

View File

@@ -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 <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAllClear/">MongoDB Query operator:
* $bitsAllClear</a>
* @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 <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAllClear/">MongoDB Query operator:
* $bitsAllClear</a>
* @since 2.1
*/
public Criteria bitsAllClear(Collection<Integer> bitPositions) {
criteria.put("$bitsAllClear", bitPositions);
return this;
}
/**
* Creates a criterion using the {@literal $bitsAllSet} operator.
*
* @param numericBitmask non-negative numeric bitmask
* @return
* @see <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAllSet/">MongoDB Query operator:
* $bitsAllSet</a>
* @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 <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAllSet/">MongoDB Query operator:
* $bitsAllSet</a>
* @since 2.1
*/
public Criteria bitsAllSet(Collection<Integer> bitPositions) {
criteria.put("$bitsAllSet", bitPositions);
return this;
}
/**
* Creates a criterion using the {@literal $bitsAnyClear} operator.
*
* @param numericBitmask non-negative numeric bitmask
* @return
* @see <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAnyClear/">MongoDB Query operator:
* $bitsAnyClear</a>
* @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 <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAnyClear/">MongoDB Query operator:
* $bitsAnyClear</a>
* @since 2.1
*/
public Criteria bitsAnyClear(Collection<Integer> bitPositions) {
criteria.put("$bitsAnyClear", bitPositions);
return this;
}
/**
* Creates a criterion using the {@literal $bitsAnySet} operator.
*
* @param numericBitmask non-negative numeric bitmask
* @return
* @see <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAnySet/">MongoDB Query operator:
* $bitsAnySet</a>
* @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 <a href="https://docs.mongodb.com/manual/reference/operator/query/bitsAnySet/">MongoDB Query operator:
* $bitsAnySet</a>
* @since 2.1
*/
public Criteria bitsAnySet(Collection<Integer> bitPositions) {
criteria.put("$bitsAnySet", bitPositions);
return this;
}
private Criteria registerCriteriaChainElement(Criteria criteria) {

View File

@@ -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;

View File

@@ -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());
}
}