【问题标题】:Fetching MongoDB documents where all array elements are NOT between a range of dates获取所有数组元素不在日期范围内的 MongoDB 文档
【发布时间】:2020-01-23 17:07:58
【问题描述】:

我正在学习 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 Criterias 与 Spring Data MongoDB 一起使用,但无法找到与“isAvailableBetween”相同的结果。

有人知道怎么做吗?

【问题讨论】:

    标签: java mongodb spring-boot spring-data-mongodb querydsl


    【解决方案1】:

    进一步研究了Mongo Criterias,我找到了解决办法!

    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 相同的附加优势,即参数可以是可选的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 2020-03-22
      • 2019-02-23
      • 1970-01-01
      • 2021-02-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多