簡體   English   中英

Cassandra nodejs驅動,如何正確更新數據

[英]Cassandra nodejs driver, how to update data correctly

我是 Cassandra 的新手,我不太清楚我的數據 model 是否正確。 我試圖根據我想在我的應用程序中進行的查詢來創建它。 我想創建和更新書籍對象,我想按作者和出版日期查找書籍。 我正在使用適用於 Cassandra 的 DataStax Node.js 驅動程序(使用 Typescript),到目前為止,這是我的架構:

CREATE TABLE IF NOT EXISTS books_by_author (
    author_id UUID,
    book_id UUID,
    book_name TEXT,
    date_published TIMESTAMP,
    PRIMARY KEY (author_id, date_published);

CREATE TABLE IF NOT EXISTS books (
    book_id uuid PRIMARY KEY,
    book_name text,
    book_description TEXT,
    date_published TIMESTAMP,
    author_id uuid,
    author_name TEXT,
 + many more columns for book details);

將 author_id 和 date_published 作為主鍵,我能夠使用 nodejs 驅動程序並在 DataStax 文檔的幫助下進行查詢:

const q = cassandra.mapping.q;

const results = await this.bookMapper.find(
          {
            authorId: '1', datePublished: q.and(q.gte(start), q.lte(end)), // given timerange for publish date, works fine
          },
          docInfo,
          options);

上面的代碼運行良好; 我可以按作者和在出版時指定日期范圍來獲取書籍列表。 bookMapper 正在映射兩個表(books_by_author、books),所以我使用它來進行所有數據庫查詢。

然后我遇到了問題。 我在我的應用程序中創建了一本書,但我給了它錯誤的發布日期,我想更改它。 所以,為了看看它是如何完成的,我創建了一個單元測試,將一本書保存到數據庫中,然后嘗試使用 bookMapper.update 來更新這本書的 datePublished 屬性。 這是我試圖實現的一些偽代碼:

const bookId = '123uuid';

const existingBook = new Book({
    id: bookId,
    name: 'The Book',
    datePublished: '2020-07-03T13:00:00.000Z',
    description: 'Book description',
    author: {
      id: '1',
      name: 'A. Author',
    }
});
... // insert existingBook to DB and read book details from DB using bookMapper.get({bookId})

const modifiedBook = new Book({
    id: bookId,
    name: 'The Book',
    datePublished: '2020-07-02T13:00:00.000Z', // modified publish date
    description: 'Modified book description', // modified the book description as well
    author: {
      id: '1',
      name: 'A. Author',
    }
});

await this.bookMapper.update(modifiedBook); // update the book

await this.bookMapper.get({bookId}); // returns the book with data from existingBook, not modifiedBook

await this.bookMapper.find(
          {
            authorId: '1', datePublished: q.and(q.gte(start), q.lte(end)),
          },
          docInfo,
          options); 
// query with author id, returns a list of 2 books, both the existingBook and modifiedBook ??

如您所見,更新實際上為數據庫創建了一個新書行,現在我有 2 本書而不是 1 本書。我不知道更新該數據的正確方法是什么。 我嘗試使用批處理:

let changes = [];
changes.push(this.bookMapper.batching.remove(exisitingBook));
changes.push(this.bookMapper.batching.insert(modifiedBook));
await this.mapper.batch(changes);

const book = await this.bookMapper.get({bookId});
--> book is null!

使用批處理刪除和插入似乎有效,因此刪除是對 DB 的最后一次調用,我將這些語句添加到我的更改數組中的順序無關緊要,它會刪除導致我最后一個 get 語句返回 null 的書。

我想使用批處理來使操作原子化。 我不想最終陷入這樣一種情況,即我首先刪除現有書籍,然后在沒有批處理的情況下將新書插入單獨的數據庫調用中,因為如果在刪除之后但插入之前發生一些錯誤,那么我將丟失我的書籍數據數據庫。

我的問題:當更新的屬性恰好是主鍵的一部分時,更新書籍數據的正確方法是什么? 謝謝你。

這是 Cassandra 的一個眾所周知的“功能” - 在批處理中,兩個語句都獲得相同的時間戳,因此DELETE操作勝過INSERT 解決此問題的唯一解決方案是為每個操作顯式設置時間戳, DELETE的時間戳低於INSERT 我不是 Node.js 開發人員,所以它應該如何看待偽代碼/CQL(Node.js 映射器應該支持在語句上設置自定義時間戳):

TS=currentTimestampInMicroseconds
BEGIN BATCH
DELETE FROM table USING TIMESTAMP TS-1 WHERE PK = ... US;
INSERT INTO table (....) VALUES (....) USING TIMESTAMP TS;
APPLY BATCH;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM