正在获取 MongoDB 个所有数组元素都不在日期范围内的文档
Fetching MongoDB documents where all array elements are NOT between a range of dates
我正在学习 Springboot 和 MongoDB。
我有这个型号class:
@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 数据 MongoDB 一起使用,但无法找到与 "isAvailableBetween" 相同结果的方法.
有人知道怎么做吗?
进一步研究 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 相同的效果,但参数可以是可选的。
我正在学习 Springboot 和 MongoDB。
我有这个型号class:
@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 数据 MongoDB 一起使用,但无法找到与 "isAvailableBetween" 相同结果的方法.
有人知道怎么做吗?
进一步研究 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 相同的效果,但参数可以是可选的。