Для запроса документов - на основе свойства объекта, который является частью списка в документе - PullRequest
0 голосов
/ 05 апреля 2020

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

Критерии: фильмы, дата выпуска которых соответствует заданному диапазону, и эта временная шкала выпуска активна

isActive = true и releaseDate> = 2020-04-20 и releaseDate <= 2020-04-21 </p>

Каждый документ имеет тип Mov ie, который содержит список movieTimeline У каждого объекта movieTimeline есть свойство isActive и releaseDate. В любой момент в фильме может быть активен отдельный movieTimeline.

Структура документа -

@Document
public class Movie extends BaseDocument
{
    private String name;
    private List<MovieTimeline> movieTimelines;
...

public class MovieTimeline
{
    private Boolean isActive;
    private LocalDateTime releaseDate;
    private String description;
...

Свойство даты выпуска имеет тип LocalDateTime в Java и хранится в 2020-04-20T05: 00: Формат 00.000 + 00: 00 в БД.

Это код, который я пытался извлечь из данных -

@Repository
public interface MovieRepository extends MongoRepository<Movie,String>
{
    List<Movie> findByMovieTimelines_ReleaseDateBetweenAndMovieTimelines_IsActive(LocalDateTime from, LocalDateTime to, boolean isActive);
}

Пример данных -

{
"id": "abc",
"name": "Rango",
"movieTimelines": [{
        "isActive": false,
        "releaseDate": "2020-02-10T11:30:00",
        "description": "ORIGINAL TIMELINE"
    }, {
        "isActive": true,
        "releaseDate": "2020-06-15T10:30:00",
        "description": "New Timeline created on 03/10/2020"
    }
]
}, {
    "id": "abcv",
    "name": "Fight Club",
    "movieTimelines": [{
            "isActive": false,
            "releaseDate": "2020-02-10T11:30:00",
            "description": "ORIGINAL TIMELINE"
        }, {
            "isActive": true,
            "releaseDate": "2020-05-18T10:30:00",
            "description": "New Timeline created on 02/05/2020"
        }
    ]
}, {
    "id": "asd",
    "name": "Death Note",
    "movieTimelines": [{
            "isActive": false,
            "releaseDate": "2020-03-09T10:30:00",
            "description": "ORIGINAL TIMELINE"
        }, {
            "isActive": false,
            "releaseDate": "2020-03-16T10:30:00",
            "description": "New Timeline created on 02/05/2020"
        }, {
            "isActive": false,
            "releaseDate": "2020-04-20T10:30:00",
            "description": "New Timeline created on 03/06/2020"
        }, {
            "isActive": true,
            "releaseDate": "2020-04-20T10:30:00",
            "description": "New Timeline created on 03/06/2020"
        }
    ]
}, {
    "id": "gfj",
    "name": "Andhadhun",
    "movieTimelines": [{
            "isActive": false,
            "releaseDate": "2020-04-13T10:30:00",
            "description": "ORIGINAL TIMELINE"
        }, {
            "isActive": true,
            "releaseDate": "2020-07-20T10:30:00",
            "description": "New Timeline created on 03/09/2020"
        }
    ]
}, {
    "id": "nojh",
    "name": "Evan Almighty",
    "movieTimelines": [{
            "isActive": true,
            "releaseDate": "2020-04-20T10:30:00",
            "description": "ORIGINAL TIMELINE"
        }
    ]
}

Ожидается-

{
    "id": "asd",
    "name": "Death Note",
    "movieTimelines": [{
            "isActive": false,
            "releaseDate": "2020-03-09T10:30:00",
            "description": "ORIGINAL TIMELINE"
        }, {
            "isActive": false,
            "releaseDate": "2020-03-16T10:30:00",
            "description": "New Timeline created on 02/05/2020"
        }, {
            "isActive": false,
            "releaseDate": "2020-04-20T10:30:00",
            "description": "New Timeline created on 03/06/2020"
        }, {
            "isActive": true,
            "releaseDate": "2020-04-20T10:30:00",
            "description": "New Timeline created on 03/06/2020"
        }
    ]
},{
    "id": "nojh",
    "name": "Evan Almighty",
    "movieTimelines": [{
            "isActive": true,
            "releaseDate": "2020-04-20T10:30:00",
            "description": "ORIGINAL TIMELINE"
        }
    ]
}

Есть ли в MongoDB какие-либо фильтры или операторы, которые можно использовать для извлечения этих документов в одном запросе?

1 Ответ

1 голос
/ 06 апреля 2020

MongoDB предоставляет $ elemMatch оператор проекции, который должен быть в состоянии удовлетворить ваши условия.

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

Вот то, что я нашел, когда я проверял ваши условия и данные выборки. Мой запрос в Mon go Shell, а не в Java / Spring, поэтому, пожалуйста, перепишите его на требуемом языке.

Так как вы хотите получать только те документы, которые имеют активную временную шкалу mov ie, isActive Атрибут в "movieTimelines" должен быть истинным. Одно это условие может быть выполнено с использованием следующего запроса:

db.collectionName.find({ "movieTimelines": { $elemMatch: { "isActive": true } } })

Дата выпуска также должна находиться в заданном диапазоне, что означает, что запрос должен обращаться к атрибуту «releaseDate» в «movieTimelines». Это условие можно запросить следующим образом:

db.collectionName.find({ "movieTimelines": { $elemMatch: { "releaseDate": { $gte: ISODate("2020-04-20T00:00:00"), $lte: ISODate("2020-04-21T00:00:00") } } } })

или

db.collectionName.find({ "movieTimelines": { $elemMatch: { "releaseDate": { $gte: ISODate("2020-04-20"), $lte: ISODate("2020-04-21") } } } })

Для приведенного выше запроса значения releaseDate являются объектами ISODate () вместо строк в моей базе данных , Строки могут быть преобразованы в объекты ISODate с использованием агрегаторов, таких как toDate , dateFromString и др. c.

Даже если значение releaseDate является строкой, Запрос будет работать, если тип данных в условии изменяется на строку. Это просто не может быть хорошей практикой.

db.collectionName.find({ "movieTimelines": { $elemMatch: { "releaseDate": { $gte: "2020-04-20", $lte: "2020-04-21" } } } })

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

db.collectionName.find({ "movieTimelines": { $elemMatch: { "isActive": true, "releaseDate": { $gte: ISODate("2020-04-20T00:00:00"), $lte: ISODate("2020-04-21T00:00:00") } } } })

Я надеюсь, что это отвечает вашим вопрос.

...