2014-10-03 97 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