2014-10-03 93 views
1

我使用弹簧数据和mongodb来创建应用程序。弹簧数据mongodb日期范围查询

我有这样的对象:

public class Room { 
    private String name; 
    private List<Date> occupied; 
} 

我想用mongodbTemplate最好让未占用日期范围房间的列表。

因此,例如,如果我有一个开始日期10/10/2014和结束日期15/10/2014我想获得列表中没有的房间列表占据日期10,11,12, 2014年10月13,14,15。

有没有人有这方面的想法?

更新:

我已经找到一种方法,通过使用该查询做到这一点:

query.addCriteria(Criteria.where("occupiedDates") 
    .ne(from).andOperator(
     Criteria.where("occupiedDates").ne(to)) 
); 

的问题是,我不能动态添加andOperator。

如果可能,我宁愿在标准内添加日期列表。

一个实例文档(只有一个记录在蒙戈存在这一个):

间(bedcount = 1,bedtype1 = 1,bedtype2 = 0,bedtype3 = 0,bedtype4 = 0,
文件类型= NULL,noofrooms = 0,占用= 0,照片=​​ NULL,rateid = 1,
ROOMNAME = NULL,roomno = 888,状态= NULL,
roomTypeID = 26060747427845848211948325568,occupiedDates = [太阳08月10
00:00 :00 EEST 2014,8月1日星期一00:00:00 EEST 2014,8月12日星期二00:00:00
EEST 2014,Wed Aug 13 00:00:00 EEST 2014],属性= {})

这是的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"} 
     } 
     } 
    } 
    } 
]} 

由此我们了解到查询应该不会返回任何内容。但它返回给我1行。

+0

这不是一个直接的答案,但你为什么不先阅读文档: http://docs.spring.io/spring-data/mongodb/docs/1.3.x/reference/html/mongo.repositories.html这真的很有帮助,并会解决您的问题。 – 2014-10-03 09:43:41

+1

当然,我已阅读文档,我找不到溶剂,否则我不会问:) – giannisapi 2014-10-03 09:50:31

+0

@帕特里克,谢谢你的好编辑:) – giannisapi 2015-06-09 06:41:28

回答

1

当我最终明白的要求,要获取所有的文件,其中 无occupied的元素属于指定的日期范围。

在蒙戈外壳完成:

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); 
+0

嗨,这个查询不起作用,不幸的是,它总是返回我所有的房间。我所做的更改是我将c2转换为BasicDBObject,因为.get返回DBObject。你有开始和结束变量,我已经把java.util.Date变量。 :( – giannisapi 2014-10-08 08:16:10

+0

@ giannisapi,对不起,C2应该是DBObject类型,我已经在回答中更正了它们,修改后它是否适用于您? – Wizard 2014-10-08 08:38:31

+0

仍然相同,它会返回所有值。标准c =在哪里应该是标准c = Criteria.where。我是否正确? – giannisapi 2014-10-08 08:44:44

0

分析路由

根据您的问题,假设有一些资源如下:

  • 占据= [D1,D2,D3,D4,D5]。 //为了便于表示,假设元素按升序排列
  • range = [start,end];

所以,你想,如果按升序排序后的数据满足下列条件之一的,返回的每个文档:

  • 开始,结束,D1,D2,D3,D4,D5 //等效于:分钟(占用)>端
  • D1,D2,D3,D4,D5,开始,结束//等效于:MAX(占用)<开始

如果元素被存储以便在占用,很容易获取最小值和最大值。 但你没有提到它,所以我认为它们本质上并不合适。

不幸的是,没有操作符可以从标准查询中的数组中获得最小值或最大值。 但是根据标准查询比较中的数组字段的特征,如果至少有一个元素或其自身满足条件,则匹配将返回true; 只返回false全部不符合标准
幸运的是,min(occupied) > end相当于NOT (at least one element <= end),这是通过以下方法实现的关键点。

履行在蒙戈外壳:

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); 
+0

嗨,我想你错误地理解了我的问题。或者我误解了你的答案:)。你读过这个: 因此,例如,如果我有一个开始日期10/10/2014和结束日期15/10/2014我想获得列表中没有列出的房间列表占领日期10,11 ,12,13,14,15 2014年10月。 被占用的列表存储的日期不是范围,所以它可能有10/10/1985,11/10/1985但它不会有10/10/1985 - 15/10/1985,而不是5天的记录,它将有5条记录,例如:1985年10月10日,11/10/1985,12/10/1985,13/10/1985,14/10/1985。我清楚地解释一下吗?感谢您的帮助 – giannisapi 2014-10-06 12:57:48

+0

@giannisapi,我明白你的意图。例如,如果有一个文件的“占用”值是:1985年10月10日,1985年11月10日,1985年12月10日,1985年13月10日,1985年10月10日,那么它应该是如果s = 02/10/1985,e = 09/10/1985,则选择它并且如果s = 02/10/1985,e = 11/10/1985因1985/1985年11月10日。这样对吗? :) – Wizard 2014-10-06 14:11:43

+0

你是绝对正确的:)我需要更仔细地看,并更好地理解你的答案。谢谢:) – giannisapi 2014-10-07 07:16:49