Spring Data JPA с Mongo @Query не будет работать с более чем одним $ или условиями - PullRequest
0 голосов
/ 21 октября 2018

У меня странная проблема с простым @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() } }
    ]
})

данные пружины 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' : [ {  } ],"

, один из перечисленных выше $ или просто пропущен .... возможно, это было намеренно, и яЯ не знаю, как с ним работать, и я не могу найти какие-либо подсказки об этом в Google и документации

Я пытаюсь многие вещи без успеха, любая помощь действительно приветствуется, спасибо:)

ОБНОВЛЕНО # 1 : я пытаюсь показать простой метод репозитория

@ Запрос с 2 $ или

@Query("{" +
  " '$or' : [" +
  "      { 'completed' : null }," +
  "      { 'completed' : false }" +
  "  ]," +
  "  '$or' : [" +
  "      { 'disabled' : null }," +
  "      { 'disabled' : false }" +
  "  ]" +
  "}")
List<FileStorage> findTest();

@ Запрос с 3 $ или

@Query("{" +
  " '$or' : [" +
  "      { 'completed' : null }," +
  "      { 'completed' : false }" +
  "  ]," +
  " '$or' : [" +
  "      { 'tested' : null }," +
  "      { 'tested' : false }" +
  "  ]," +
  "  '$or' : [" +
  "      { 'disabled' : null }," +
  "      { 'disabled' : false }" +
  "  ]" +
  "}")
List<FileStorage> findTest();

Log

find using query: { "$or" : [{ "disabled" : null }, { "disabled" : false }] } 

та же проблема.даже с двумя или более простыми $ или без параметров, та же ошибка, он использует только один $ или другие исчезают .....

ОБНОВЛЕНИЕ # 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 } } }] }

эта проблема превращается в настоящую боль в ..., что происходит, это всеразные и возможные способы, всегда с одним и тем же концом, данные Spring не будут работать с более чем одним $ или, и это обрезает некоторые запросы без причины .......

UPDATE # 3

возможно, проблема объясняется тем, что это изображение похоже на $ или является ключом аналогичного хэш-карты, а последнее endDateTime заменяет startDateTime : (

на этом изображении у меня есть 4 индексных ключа, текущий 4 является реальным 5, и я потерял индекс 4, который является startDateTime .........

Пожалуйста, проверьте изображение1 здесь , и изображение2 здесь У меня нет репутации (для публикации изображений вам нужно как минимум 10 репутаций.)

введитеописание изображения здесь

ОБНОВЛЕНИЕ # 4 :

После борьбы с запросами и критериями и поиска новой проблемы wесли использовать более одного $ или ......... продолжаются кошмарные приключения, хе-хе

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, он работаетно это неудачный запрос, полный СУХОГО, мне действительно это не нравится, и я знаю, что есть лучший способ сделать это, весенние парни действительно потрясающие, и я не верю, что Монго не может с этим работатьтипы запросов, которые являются базовыми

вышеупомянутый запрос, который работает с 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);

log

{ "$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 }] }

завтра я пытаюсь очистить код и опубликовать свои выводы ..... Мне не очень нравится этот код ......

но это слишком странно, что мы можем использовать необработанные запросы в данных весны, слишком странно !!!!а может я не знаю как это сделать

Ответы [ 2 ]

0 голосов
/ 29 апреля 2019

Для меня это работало, чтобы сделать "и" явным, как это:

            "{" + //
            "  '$and': [" + //
            "    { 'status': ?0 }," + //
            "    { 'publishedFrom': { $lte: ?1 } }," + //
            "    { '$or': [" + //
            "      { 'publishedUntil': null }," + //
            "      { 'publishedUntil': { $gte: ?1 } }" + //
            "    ] }," + //
            "    { 'interests': { $in: ?2 } }," + //
            "    { '$or': [" + //
            "      { 'tenantNumbers': { $size: 0 } }," + //
            "      { 'tenantNumbers': { $in: ?3 } }" + //
            "    ] }" + //
            "  ]" + //
            "}" 
0 голосов
/ 22 октября 2018

Правда ли, что вы пытаетесь выбрать документы, которые соответствуют заданным критериям, таким как "пользователь": "somevalue" И "businessCategory": "somevalue" И {"startdate" равен нулю или меньше, чем текущая дата времени} и {enddate равен нулю или больше, чем текущее время даты. Если аннотация запроса не работает.Попробуйте использовать классы Criteria и Query из данных Spring mongo в самом методе java.Мне просто интересно узнать, работает ли следующее для вас.Если да, то вы можете поиграть с 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);
...