我有一个奇怪的问题,一个简单的@Query
与弹簧数据和mongodb,问题是当我使用多个$or
条件,它似乎不能同时使用2个或更多$or
条件,或者我不能把它工作,它只能同时使用一个$or
,另一个被省略,我们可以在日志和最终结果集中看到它,其中一个日期($或)未被过滤:(
mongodb查询
db.getCollection('fileStorage').find({
'user' : { '$ref' : 'user' , '$id' : ObjectId('5bafc1ab40005e285dbafadc')},
'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('5bc0ca4336c9175f7ce6c91d')}},
'completed' : true,
'disabled' : false,
$or : [
{ 'startDateTime' : null },
{ 'startDateTime' : { '$lte' : new Date() } }
],
$or : [
{ 'endDateTime' : null },
{ 'endDateTime' : { '$gte' : new Date() } }
]
})
spring data jpa @Query
@Query("{ " +
"'user' : {'$ref': 'user', '$id': ?#{[0]} }, " +
"'businessCategory' : { '$ne' : {'$ref': 'businessCategory', '$id': ?#{[1]} } }, " +
"'completed' : ?#{[2]}, " +
"'disabled' : ?#{[3]}, " +
"'$or' : [ { 'startDateTime' : null }, { 'startDateTime' : { '$lte' : ?#{[4]} } } ], " +
"'$or' : [ { 'endDateTime' : null }, { 'endDateTime' : { '$gte' : ?#{[4]} } } ] " +
"}")
List<FileStorage> getPlayList(ObjectId userId, ObjectId excludeBusinessCategory, boolean completed, boolean disabled, Date currentDateTime, Sort sort);
在日志显示
find using query:
{ "user" : { "$ref" : "user", "$id" : { "$oid" : "5bafc1ab40005e285dbafadc" } }, "businessCategory" : { "$ne" : { "$ref" : "businessCategory", "$id" : { "$oid" : "5bc0ca4336c9175f7ce6c91d" } } }, "completed" : true, "disabled" : false, "$or" : [{ "endDateTime" : null }, { "endDateTime" : { "$gte" : { "$date" : 1540077045932 } } }] }
在上面的日志中,我们看不到startDateTime,
"'$or' : [ { 'startDateTime' : null }, { 'startDateTime' : { '$lte' : ?#{[4]} } } ], " +
以上startDateTime
条件丢失.....
问题是我需要$或者两个,但只有一个同时工作,在上面的例子只有endDateTime
工作,
如果我评论endDateTime
,它开始与startDateTime
合作,它不会用这样的简单的事情工作
"'$or' : [ { } ], '$or' : [ { } ],"
上面的一个$或者简单地省略....也许它是故意的,我不知道如何使用它,我无法在谷歌和文档中找到任何线索
我尝试了许多没有成功的事情,非常感谢任何帮助,谢谢:)
更新#1:我尝试使用简单的存储库方法来显示问题
@Query with 2 $或
@Query("{" +
" '$or' : [" +
" { 'completed' : null }," +
" { 'completed' : false }" +
" ]," +
" '$or' : [" +
" { 'disabled' : null }," +
" { 'disabled' : false }" +
" ]" +
"}")
List<FileStorage> findTest();
@Query with 3 $或
@Query("{" +
" '$or' : [" +
" { 'completed' : null }," +
" { 'completed' : false }" +
" ]," +
" '$or' : [" +
" { 'tested' : null }," +
" { 'tested' : false }" +
" ]," +
" '$or' : [" +
" { 'disabled' : null }," +
" { 'disabled' : false }" +
" ]" +
"}")
List<FileStorage> findTest();
日志
find using query: { "$or" : [{ "disabled" : null }, { "disabled" : false }] }
同样的问题。即使只有2个或更多的简单$或没有参数,相同的错误,它只使用一个$或,其他(s)消失.....
更新#2:使用MongoTemplate和BasicQuery时会出现问题??????? WTF
String stringQuery = String.format("{\n" +
" 'user' : { '$ref' : 'user' , '$id' : ObjectId('%s')},\n" +
" 'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('%s')}},\n" +
" 'completed' : %b,\n" +
" 'disabled' : %b,\n" +
" '$or' : [\n" +
" { 'startDateTime' : null },\n" +
" { 'startDateTime' : { '$lte' : new Date() } }\n" +
" ],\n" +
" '$or' : [\n" +
" { 'endDateTime' : null },\n" +
" { 'endDateTime' : { '$gte' : new Date() } }\n" +
" ]\n" +
"}", userId, businessCategoryId, completed, disabled) ;
BasicQuery query = new BasicQuery(stringQuery);
files = mongoTemplate.find(query, FileStorage.class);
log:同样的问题它会削减startDateTime
{ "user" : { "$ref" : "user", "$id" : { "$oid" : "5bafc1ab40005e285dbafadc" } }, "businessCategory" : { "$ne" : { "$ref" : "businessCategory", "$id" : { "$oid" : "5bc0ca4336c9175f7ce6c91d" } } }, "completed" : true, "disabled" : false, "$or" : [{ "endDateTime" : null }, { "endDateTime" : { "$gte" : { "$date" : 1540157706740 } } }] }
这个问题正在变成一个真正的痛苦......,它发生了什么不同和可能的方式,总是有相同的结果,弹簧数据将无法使用多个$或者,它会削减一些查询没有理由.......
更新#3
也许这个问题是由那个图像解释的,就像$或者是类似hashmap的关键,最后一个endDateTime取代了startDateTime :(
在那个图像中我有4个索引键,当前4是真正的5,我丢失了索引4即startDateTime .........
请检查image1 here和image2 here我没有声望(您需要至少10个声望才能发布图片。)
更新#4:
在使用Queries和Criterias进行战斗并在使用多个$或.........时发现一个新问题噩梦冒险继续eheheeh
org.springframework.data.mongodb.InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second '$or' expression specified as '$or
我找到了一个如何解决这个问题的丑陋方式,使用上面的查询与BasicQuery,它的工作但它是一个蹩脚的查询,充满了DRY,我真的不喜欢它,我知道有更好的方法来做到这一点,春天的家伙真的很棒,我不相信mongo无法使用这种查询,这是基本的
上面的查询适用于BasicQuery,有一个$或,但充满重复的代码,来做这项工作:(
查询x 4,适用于所有条件
db.getCollection('fileStorage').find({
'$or' : [
{
'user' : { '$ref' : 'user' , '$id' : ObjectId('5bafc1ab40005e285dbafadc')},
'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('5bc0ca4336c9175f7ce6c91d')}},
'completed' : true,
'disabled' : false,
'startDateTime' : { '$lte' : new Date() },
'endDateTime' : { '$gte' : new Date() }
},
{
'user' : { '$ref' : 'user' , '$id' : ObjectId('5bafc1ab40005e285dbafadc')},
'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('5bc0ca4336c9175f7ce6c91d')}},
'completed' : true,
'disabled' : false,
'startDateTime' : null,
'endDateTime' : null
},
{
'user' : { '$ref' : 'user' , '$id' : ObjectId('5bafc1ab40005e285dbafadc')},
'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('5bc0ca4336c9175f7ce6c91d')}},
'completed' : true,
'disabled' : false,
'startDateTime' : { '$lte' : new Date() },
'endDateTime' : null
},
{
'user' : { '$ref' : 'user' , '$id' : ObjectId('5bafc1ab40005e285dbafadc')},
'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('5bc0ca4336c9175f7ce6c91d')}},
'completed' : true,
'disabled' : false,
'startDateTime' : null,
'endDateTime' : { '$gte' : new Date() }
}
]
})
代码,2 x查询,只是一个例子
String stringQuery = String.format("{\n" +
"'$or' : [{" +
" 'user' : { '$ref' : 'user' , '$id' : ObjectId('" + userId + "')}," +
" 'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('" + businessCategoryId + "')}}," +
" 'completed' : " + completed + "," +
" 'disabled' : " + disabled + "," +
" 'startDateTime' : { '$lte' : new Date() }," +
" 'endDateTime' : { '$gte' : new Date() }" +
"}," +
"{" +
" 'user' : { '$ref' : 'user' , '$id' : ObjectId('" + userId + "')}," +
" 'businessCategory' : { '$ne' : { '$ref' : 'businessCategory', '$id' : ObjectId('" + businessCategoryId + "')}}," +
" 'completed' : " + completed + "," +
" 'disabled' : " + disabled + "," +
" 'startDateTime' : null," +
" 'endDateTime' : null" +
"}]" +
"}", userId, businessCategoryId, completed, disabled);
BasicQuery basicQuery = new BasicQuery(stringQuery/*, "{ user : 1, businessCategory : 1}"*/);
files = mongoTemplate.find(basicQuery, FileStorage.class);
日志
{ "$or" : [{ "user" : { "$ref" : "user", "$id" : { "$oid" : "5bafc1ab40005e285dbafadc" } }, "businessCategory" : { "$ne" : { "$ref" : "businessCategory", "$id" : { "$oid" : "5bc0ca4336c9175f7ce6c91d" } } }, "completed" : true, "disabled" : false, "startDateTime" : { "$lte" : { "$date" : 1540249026648 } }, "endDateTime" : { "$gte" : { "$date" : 1540249026648 } } }, { "user" : { "$ref" : "user", "$id" : { "$oid" : "5bafc1ab40005e285dbafadc" } }, "businessCategory" : { "$ne" : { "$ref" : "businessCategory", "$id" : { "$oid" : "5bc0ca4336c9175f7ce6c91d" } } }, "completed" : true, "disabled" : false, "startDateTime" : null, "endDateTime" : null }] }
明天我会尝试清理代码,并发布我的结论......我真的不喜欢那些代码......
但它太奇怪了我们可以在spring数据mongo中使用原始查询,太奇怪!!!!或者我可能不知道该怎么做
您是否尝试获取与“user”之类的设置条件相匹配的文档:“somevalue”和“businessCategory”:“somevalue”AND {“startdate”为null或小于当前日期时间}和{“enddate”是null或大于当前日期时间}如果查询注释不起作用。尝试在java方法本身中使用spring data mongo中的Criteria和Query类。我很想知道以下是否适合您。如果是,那么您可以在第一个标准中使用Or来查看是否可以将其自身组合而不是编写其他条件然后使用OrOperator
@Autowired
private MongoOperations cosmosTemplate;
List<Criteria> citerion = new ArrayList<>();
Criteria criteria = new Criteria();
criteria = Criteria.where("User")
.is("somevalue")
.and("businessCategory")
.is("somevalue")
.and("completed")
.is("somevalue")
.and("disbaled")
.is("somevalue")
.and("startDateTime")
.is(null);
criterion.add(criteria);
criteria = Criteria.where("User")
.is("somevalue")
.and("businessCategory")
.is("somevalue")
.and("completed")
.is("somevalue")
.and("disbaled")
.is("somevalue")
.and("startDateTime")
.lte("somedate");
criterion.add(criteria);
Query query = Query.query(new Criteria().orOperator(citerion.toArray(new Criteria[citerion.size()]))).with(new Sort(Sort.Direction.ASC,"user"));
return mongoTemplate.find(queryuery, <<yourclass>>.class);
对我而言,它有助于使“和”明确,如下所示:
"{" + //
" '$and': [" + //
" { 'status': ?0 }," + //
" { 'publishedFrom': { $lte: ?1 } }," + //
" { '$or': [" + //
" { 'publishedUntil': null }," + //
" { 'publishedUntil': { $gte: ?1 } }" + //
" ] }," + //
" { 'interests': { $in: ?2 } }," + //
" { '$or': [" + //
" { 'tenantNumbers': { $size: 0 } }," + //
" { 'tenantNumbers': { $in: ?3 } }" + //
" ] }" + //
" ]" + //
"}"