2017-09-24 16 views
0

我想使用indexedDB來管理典型電子郵件收件箱中的電子郵件列表。每個電子郵件剛剛三個屬性:如何顯示來自每個發件人的最新電子郵件(每組獲得最高1行)?

  1. Time - 時間的電子郵箱收到
  2. Sender - 發件人
  3. 的電子郵件地址
  4. Subject - 電子郵件的標題

我應該如何模擬數據在indexedDB和我應該如何制定查詢來實現以下內容:

  1. 列出每個Sender(時間,發件人,主題)的最新電子郵件,由每個最新電子郵件的Time(降序)排序。此列表顯示每個Sender的最新電子郵件。
  2. 鑑於Sender,列出此Sender的所有電子郵件,訂購Time

我對NoSql完全陌生。我想我可以通過爲Sender創建索引並打開索引的遊標來相對簡單地實現第二個查詢。

對於第一個查詢,我想維護一個單獨的商店,Latest,它保留每個發件人的最新電子郵件。每次收到新郵件時,都必須將Put分成Latest。顯然,這是充滿了問題,我需要幫助「正確」的方式來做到這一點。

回答

0

作爲一個猜測,它將涉及使用基於多個屬性的索引。這是一個有點反直覺的和很難得到正確的在第一,但基本上是:

function onupgradeneeded(event) { 
    // ... 
    // make sure to use explcit and exact property names in second 
    // param to createIndex 
    store.createIndex('sender-time', ['sender', 'time']); 
} 

function get_latest() { 
    // ... 
    var index = store.index('sender-time'); 

    // use prev so that the sort order is descending instead of 
    // ascending 
    // first arg is the range, we are not limiting items in any way 
    // here, at least explictly. implicitly we are filtering out items 
    // without a sender or without a time since missing values cause 
    // the object to be excluded from the index. 
    var request = index.openCursor(null, 'prevunique'); 

    request.onsuccess = function() { 
    // This iterates over all items. The trick then is to advance the 
    // cursor to the prev unique item. Since items in the index are 
    // ordered first by sender, then by time, jumping to prev unique 
    // sender skips over the other records for the same sender you 
    // would see if you normally just advanced the cursor. 

    } 
} 

最糟糕的情況是,你加載的所有項目,然後做所有的過濾和內存中的排序。與最壞情況相比,上面的代碼減少了反序列化對象的數量(從indexedDB加載到js land),並且這些項目已經排序,nextUnique邏輯發生在C++ land而不是Js land,所以它的評估速度更快。

對於情況#2,您可以使用range參數來執行openCursor。如果要將時間從最舊到最新排序,則不再需要通過prev。

function get_sender() { 
    var index = store.index('sender-time'); 
    var lowerBound = ['sender-value-here', smallest date possible in js]; 
    var upperBound = ['the-same-sender-value-here', largest date possible in js]; 
    var range = IDBKeyRange.bounds(lowerBound, upperBound); 
    // NOTE: above might be wrong I forget, you have to make the 
    // bounds inclusive, so that sender matches and the bounds do not 
    // result in excluding all records 
    // again here you don't need 'prev' 2nd param unless you want 
    // reverse order 
    var request = index.openCursor(range); 
} 

本質寄件人時間指數是有點像一個SELECT * ORDER BY sender ASC, time ASC中間結果,你再掃描。因此,在第一種情況下,您可以使用nextUnique跳轉到下一個新的發件人並獲取他們的第一個項目,然後再跳過。在第二種情況下,您使用的是Where子句,如SELECT * FROM table WHERE sender >= sender && sender <= sender && time >= min-time && time <= max-time。但請注意這是一個嚴重的簡化。實際上,我們正在利用這樣一個事實,即我們繞過了indexedDB中pseudo-where子句的短路評估,如果我們有更寬鬆的發送者條件,那麼這將導致所有事情都搞砸了。但在這種情況下,發送者可能沒有條件(secnario 1,我們只是使用排序順序),或者在情況2中,發送者始終是相同的發送者,並且我們知道布爾子句的第一部分始終爲真,因此第二個子句總是評估。

+0

感謝您的建議。你會考慮在我的問題中描述一個獨立的商店'Latest'嗎?一個可行的選擇? –

+0

除非這是唯一的方法。使用nosql dbs,您會追求更高性能而不是普通形式。 – Josh

+0

請注意,next或prev unique可能無法正常工作,因爲發件人和時間都是關鍵路徑的一部分。也許嘗試使用提前或繼續只發件人,而如果可能的話。 – Josh

1

使用IndexedDB封裝器JsStore您可以創建一個表,用於存儲具有自動增量列(例如Id)的郵件並使用此列(Id)對數據進行排序。

與本案#2凝視:

從發件人檢索所有的電子郵件

var Connection = new JsStore.Instance("Database_name"); 
Connection.select({ 
    From: "Inbox", // Inbox is your table name 
    Where:{ 
     Sender: sender_email 
    }, 
    Order: { 
     By: "Id", 
     Type: "desc" 
    }, 
    OnSuccess:function (results){ 
     console.log(results); 
    }, 
    OnError:function (error) { 
     console.log(error); 
    } 
}); 

情況#1:

這將是很容易檢索如果我們可以在JsStore中使用GROUP BY子句,但是不幸的是它沒有在當前版本的JsStore中提供,但它可能會支持其next release

直到那時我們可以過濾郵件的完整記錄或可以使用發件人的電子郵件ID一個接一個地獲取。

過濾上完整記錄

var Connection = new JsStore.Instance("Database_name"); 
Connection.select({ 
    From: "Inbox", // Inbox is the table name 
    Order: { 
     By: 'Id', 
     Type: "desc" 
    }, 
    OnSuccess:function (results){ 
    var sendersName = []; 
    var filteredMails = results.filter(function(mail){ 
     if(sendersName.indexOf(mail.sender) == -1){ 
      sendersName.push(mail.sender); 
      return mail; 
     } 
    }); 
    console.log(filteredMails); 
    }, 
    OnError:function (error) { 
     console.log(error); 
    } 
}); 

一個獲取最新的郵件爲每個發件人一個推到一個數組:

var mails=[]; 
senders_email.forEach(function(value){ // keep the list of senders email in the array "sender_email" 
    Connection.select({ 
     From:'Inbox', 
     Where:{ 
      Sender:value 
     }, 
     Limit:1, 
     Order: { 
      By: 'Id', 
      Type: "desc" 
     }, 
     OnSuccess:function(result){ 
      result.length > 0 && mails.push(result[0]); 
     }, 
     OnError:function(err){ 
      console.log(err); 
     } 
    }) 
}); 

你可以有它的SQL來看看用於查詢IndexedDB的official site的類型語法。您可以輕鬆地解釋上述代碼。

相關問題