获取所有数组元素不在日期范围内的MongoDB文档

问题描述 投票:0回答:1

我正在学习Springboot和MongoDB。

我有这个模型课:

@Data
@Document(collection = "accommodations")
public class Accommodation {

    @Id
    private String accommodationId;
    @TextIndexed
    private String title;
    @Indexed
    private double pricePerNight;
    private int guests;
    @Indexed
    private double rating;
    private AccommodationType type;
    private String description;
    private boolean listed;
    private Address address;
    private Landlord landlord;
    private List<Image> images;
    private List<Review> reviews;
    private List<Booking> bookings;

    public Accommodation(String title, double pricePerNight, int guests, AccommodationType type, String description, Address address, Landlord landlord) {
        this.title = title;
        this.pricePerNight = pricePerNight;
        this.guests = guests;
        this.type = type;
        this.description = description;
        this.listed = true;
        this.address = address;
        this.landlord = landlord;
        this.rating = 0.0;
        this.images = new ArrayList<>();
        this.reviews = new ArrayList<>();
        this.bookings = new ArrayList<>();
    }

    public boolean isAvailableBetween(LocalDate checkin, LocalDate checkout) {
        return this.bookings
                .stream()
                .noneMatch(b -> (b.getCheckin().isBefore(checkout) || b.getCheckin().isEqual(checkout)) &&
                        (b.getCheckout().isAfter(checkin)) || b.getCheckout().isEqual(checkin));
    }

}

我目前正在使用方法“ isAvailableBetween”来筛选在特定日期范围内(预订和退房)已经预订的住宿。

我想通过Mongo查询实现相同的功能,但不知道如何实现。

这是我到目前为止尝试过的(忽略查询中的其他过滤器:]

@Repository
public interface AccommodationRepository extends MongoRepository<Accommodation, String>, QuerydslPredicateExecutor<Accommodation> {    

    @Query("{" +
            "$and: [" +
                "{listed:true}," +
                "{pricePerNight:{$lte:?0}}," +
                "{guests:{$gte:?1}}," +
                "{rating:{$gte:?2}}," +
                "{'landlord.trusted':?3}," +
                "{bookings:{$not:{$elemMatch:{checkin:{$lte:?5},checkout:{$gte:?4}}}}}" +
            "]" +
            "}")
    Page<Accommodation> findAccommodationsByFilter(Pageable pageable,
                                                   Double pricePerNight,
                                                   Integer guests,
                                                   Double rating,
                                                   Boolean trusted,
                                                   LocalDate checkin,
                                                   LocalDate checkout

}

[还尝试将QueryDSL和Mongo标准与Spring Data MongoDB结合使用,但无法找到一种与“ isAvailableBetween”相同的结果的方法。

有人知道该怎么做吗?

java mongodb spring-boot spring-data-mongodb querydsl
1个回答
0
投票

[进一步研究了Mongo标准之后,我找到了解决方案!

public Page<Accommodation> findAccommodationsByFilter(AccommodationFilter filter, Pageable pageable) {

    Criteria listedTrue = where("listed").is(true);
    Query query = query(listedTrue);
    filter.pricePerNight().map(where("pricePerNight")::lte).ifPresent(query::addCriteria);
    filter.guests().map(where("guests")::gte).ifPresent(query::addCriteria);
    filter.type().map(where("type")::is).ifPresent(query::addCriteria);
    filter.rating().map(where("rating")::gte).ifPresent(query::addCriteria);
    filter.trustedLandlord().map(where("landlord.trusted")::is).ifPresent(query::addCriteria);
    filter.country().map(where("address.country")::is).ifPresent(query::addCriteria);
    filter.city().map(where("address.city")::is).ifPresent(query::addCriteria);

    if(filter.checkout().isPresent() && filter.checkin().isPresent()){
        Criteria c = where("bookings")
                .not()
                .elemMatch(where("checkin").lte(filter.checkout().get())
                        .and("checkout").gte(filter.checkin().get()));

        query.addCriteria(c);
    }

    long total = this.mongoOperations.count(query, Accommodation.class);

    query.with(pageable);
    List<Accommodation> accommodations = this.mongoOperations.find(query, Accommodation.class);

    return new PageImpl<>(accommodations, pageable, total);
}

这与@Query取得了相同的效果,另外的优点是参数可以是可选的。

© www.soinside.com 2019 - 2024. All rights reserved.