在SQL中,你可以执行以下操作;
SELECT * FROM CUSTOMERS WHERE ID=43 AND 1=1
如何在 Java 中将"1=1"或"4<6"等布尔表达式作为标准提供给 MongoDB 逻辑运算符?
例如,我可以做到;
collection.find("$or",Arrays.asList(new Document("field1",value1),new Document("field2",value2)))
但是,上述标准始终基于已经存在的字段,而我想做的是更多类似的东西(不会编译);
collection.find("$and",Arrays.asList(new Document(1,1),new Document("field2",value2)))
我需要这个的原因是因为我有一个"$or"标准列表,但这个列表可能是空的 - 在这种情况下,我根本不想有标准。
更新 1
虽然 @gil.fernandes 的解决方案非常适合find
查询,但它不适用于聚合查询(这也是我需要的);
AggregateIterable aggregationQuery = collection.aggregate(Arrays.asList(
[...]
new Document("$match", new Document("$or", Arrays.asList(new Document("$where","1==1"))))
));
MongoCommandException: 命令失败,出现错误 16395:"$where 是 不允许在$match聚合表达式内
"
关于我们如何在聚合运算符中使用"1=1"逻辑$match有什么想法吗?
更新 2
我使用 mongo 服务器版本 3.4.7 应用了@Veeram的第二个解决方案 但是,如果我将addFields
和match
对象包含在聚合查询中,则得到 0 个结果。 如果我删除它们,我会得到所有结果。
collection = mongoClient.getDatabase("testDatabase").getCollection("testColletion");
collection.insertOne(new Document("testField","testValue"));
Bson addFields = Aggregates.addFields(new Field<>("cmp", new Document("$or", Arrays.asList(new Document("$eq", Arrays.asList(1, 1))))));
Bson match = Aggregates.match(Filters.eq("cmp", 1));
AggregateIterable aggregationQuery = collection.aggregate(Arrays.asList(
new Document("$match", new Document("testField", "testValue")),
addFields,
match
));
boolean hasDocuments = aggregationQuery.iterator().hasNext()
您可以在 3.6 mongo 服务器版本上$expr
。
import static com.mongodb.client.model.Aggregates.addFields;
import static com.mongodb.client.model.Aggregates.match;
import static com.mongodb.client.model.Filters.*;
import static java.util.Arrays.asList;
类似的东西
Bson match = match(expr(new Document("$or", asList(new Document("$eq", asList(1, 1))))));
AggregateIterable aggregationQuery = collection.aggregate(asList(
[...]
match
));
这应该输出类似
{ "$match" : { "$expr" : { "$or" : [{ "$eq" : [1, 1] }] } } }
对于较低版本 3.4,您可以使用$addFields
和$match
的组合来实现类似的查询。
Bson addFields = addFields(new Field<>("cmp", new Document("$or", asList(new Document("$eq", asList(1, 1))))));
Bson match = match(eq("cmp", true));
AggregateIterable aggregationQuery = collection.aggregate(asList(
[...]
addFields,
match
));
这应该输出类似
{ "$addFields" : { "cmp" : { "$or" : [{ "$eq" : [1, 1] }] } } }
{ "$match" : { "cmp" : true } }
在普通的MongoDB Javascript查询中,你可以用1=1
来表达过滤器。
下面是一个示例:
db.customer.find(
{"customer.id" : "1081965259", "customer.status": "Live", "$where": "1 == 1"},
{"customer.id": 1, "customer.status": 1})
.pretty();
相关查询"$where": "1 == 1"
。如果将其设置为"$where": "1 == 2"
则永远不会检索任何结果。
更新
您还可以在 or 语句中使用此子句:
db.customer.find({"$or": [{ "customer.id" : "1081959342" }, { "$where": "1 == 1" }]});
注意:这实际上返回集合中的所有记录。
更新 2
实际上,$or
子句与$where
的组合也可以在Java中完成,也可以进行简单组合。下面是一个示例:
// Or Logic
private static FindIterable<Document> findDocumentByKeysOrClause(String id, MongoCollection<Document> collection) {
BasicDBObject query = new BasicDBObject();
List<BasicDBObject> orQueryList =
Arrays.asList(new BasicDBObject("customer.customerId.sourceKeys.keies.id", id),
new BasicDBObject("$where", "1 == 1"));
query.put("$or", orQueryList);
return collection.find(query);
}
这是我的完整测试类供参考:
import com.mongodb.BasicDBObject;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import org.bson.types.ObjectId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Tests Mongo custom queries.
*/
public class MongoClauseTester {
public static void main(String[] args) {
MongoClient mongoClient = new MongoClient("localhost", 27017);
MongoDatabase db = mongoClient.getDatabase("customers");
MongoCollection<Document> customerCollection = db.getCollection("customer_UK");
final FindIterable<Document> documentByKeysOrClause = findDocumentByKeysOrClause("C@0248870263@DHUB", customerCollection);
MongoCursor<Document> iter = documentByKeysOrClause.iterator();
for(int i = 0; i < 3 && iter.hasNext(); i++) {
System.out.println(iter.next().toJson());
}
}
// And logic
private static FindIterable<Document> findDocumentByKeys(String id, MongoCollection<Document> collection) {
BasicDBObject query = new BasicDBObject();
query.put("customer.customerId.sourceKeys.keies.id", id);
query.put("$where", "1 == 1");
return collection.find(query);
}
// Or Logic
private static FindIterable<Document> findDocumentByKeysOrClause(String id, MongoCollection<Document> collection) {
BasicDBObject query = new BasicDBObject();
List<BasicDBObject> orQueryList =
Arrays.asList(new BasicDBObject("customer.customerId.sourceKeys.keies.id", id),
new BasicDBObject("$where", "1 == 1"));
query.put("$or", orQueryList);
return collection.find(query);
}
}
以下是使用的MongoDB驱动程序的版本:
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.1</version>
</dependency>