我正在使用mongodb的spring数据来创建一个应用程序。
我有这个对象:
public class Room {
private String name;
private List<Date> occupied;
}
我希望使用mongodbTemplate
来获取未占用日期范围的房间列表。
因此,例如,如果我有一个开始日期10/10/2014和结束日期15/10/2014我想得到列表中没有的房间列表占用日期10,11,12,13 ,2014年10月14,15。
有没有人对此有任何想法?
更新
通过使用此查询,我找到了一种方法:
query.addCriteria(Criteria.where("occupiedDates")
.ne(from).andOperator(
Criteria.where("occupiedDates").ne(to))
);
问题是我无法动态添加andOperator。
如果可能的话,我更愿意在标准内添加日期列表。
示例文档是(mongo中只存在一条记录):
房间(床数= 1,床型1 = 1,床型2 = 0,床型3 = 0,床型4 = 0,
filetype = null,noofrooms = 0,occupancy = 0,photo = null,rateid = 1,
roomname = null,roomno = 888,status = null,
roomTypeID = 26060747427845848211948325568,occupiedDates = [Sun Aug 10
00:00:00 EEST 2014,Mon Aug 11 00:00:00 EEST 2014,8月12日00:00:00
EEST 2014,8月13日星期三00:00:00 EEST 2014],attributes = {})
这是构建wyeru的代码:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
Date to = null;
Date from = null;
try {
to = dateFormat.parse("12-08-2014 00:00:00");
from = dateFormat.parse("10-08-2014 00:00:00");
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
DBObject c1 = new BasicDBObject("occupied", null);
DBObject c2 = BasicDBObjectBuilder.start()
.push("occupied").push("$not")
.push("$elemMatch").add("$gte", from).add("$lte", to).get();
Criteria c = Criteria.where("$or").is(Arrays.asList(c1, c2));
Query query = new Query().addCriteria(c);
List<Room> rooms = mongoTemplate.find(query, Room.class);
此查询发送到mongodb
{ "$or" : [
{ "occupied" : null } ,
{ "occupied" :
{ "$not" :
{ "$elemMatch" :
{ "$gte" : { "$date" : "2014-08-09T21:00:00.000Z"} ,
"$lte" : { "$date" : "2014-08-11T21:00:00.000Z"}
}
}
}
}
]}
从中我们知道查询应该什么也不返回。但它让我回到了一排。
答案 0 :(得分:1)
根据我最终理解的要求,您想要获取其中的所有文档
occupied
的任何元素都不属于指定的日期范围。
在mongo shell上完成:
db.b.find({
$or : [{
occupied : null
}, {
occupied : {
$not : {
$elemMatch : {
$gte : start,
$lte : end
}
}
}
}]
}).pretty();
然后转换为Java代码,如下所示:
// Because "Criteria" has a bug when invoking its method "elemMatch",
// so I build the criteria by the driver directly, almost.
DBObject c1 = new BasicDBObject("occupied", null);
DBObject c2 = BasicDBObjectBuilder.start().push("occupied").push("$not").
push("$elemMatch").add("$gte", start).add("$lte", end).get();
Criteria c = where("$or").is(Arrays.asList(c1, c2));
Query query = new Query().addCriteria(c);
List<Room> rooms = mongoTemplate.find(query, Room.class);
答案 1 :(得分:0)
根据您的问题,假设有以下资源:
因此,您希望在按升序排序后,如果其数据满足以下条件之一,则返回每个文档:
如果元素按占用顺序存储,则很容易获取最小值和最大值。 但是你没有提到它,所以我认为它们本身并不合适。
不幸的是,没有运算符可以在标准查询中从数组中获取最小值或最大值。
但是根据标准查询对比数组字段的特性,
如果至少有一个元素或其自身满足标准,则匹配将返回true;
返回false只会使所有标准都失败
很幸运地发现min(occupied) > end
等同于NOT (at least one element <= end)
,这是通过以下方法实现的关键点。
实现mongo shell:
db.b.find({
$or: [{
occupied: {
$not: {
$lte: end
}
}
}, {
occupied: {
$not: {
$gte: start
}
}
}]
}). pretty();
然后翻译成这样的Java代码:
Criteria c = new Criteria().orOperator(where("occupied").not().lte(end),
where("occupied").not().gte(start));
Query query = new Query().addCriteria(c);
List<Room> rooms = mongoTemplate.find(query, Room.class);