2017-10-13 53 views
0

LocalDBを使用してオフライン注文の作成を管理するWebアプリケーションを実現する必要があります。IndexedDB - 大量のデータを格納する正しい方法

私はこの時点で、Angular2/TypescriptにDexieを使ってLocalDBを実装しています。

  • お客様(+1000記録)
  • 製品(2000の記録)
  • 製品
  • 価格:私がしなければならない何

    が管理できるようにするために、データベースを実現していますお客様ごとに定義されています+(100.000レコード)

  • 注文数(少ないデータ)

等...

それは、製品、顧客、および価格は、ロットまたは記録されているので...

私の質問があり、データのLOFを管理する必要があります:

私がしている場合私は一時的な注文を構成するときに、SQL ServerまたはMySqlのような共通のリレーショナルデータベース を使用してこのdbを実現しました...

しかし、私はIndexedDBで何をしなければなりませんか?より良い

ITSはidMaterial /数量を使用してMySQL /のSQLServerのためのような一時的な順序を保存し、(必要な)製品の情報 をretrive INNER JOINを行うことによって、またはその優れたローカル・テーブル内の製品のすべての情報を保存するためにします/ INNER JOINクエリを避けるために、価格 ?

2000以上の製品と100,000以上の製品を結合するテーブル間でINNER JOINを実行できますか?

サポートありがとうございます。

答えて

1

IndexedDBは、テーブル、行、トランザクションが異なる名前を付けられていても(テーブル=オブジェクトストア、行=オブジェクト)、SQLデータベースのように多くのアーキテクチャを備えています。

Dexieを使用すると、外部キーを使用した一般的な結合を行うのは簡単です。 IndexedDBは外部キーの制約をチェックしませんが、SQL結合に似たクエリを実行できます。

dexieへのアドオン、dexie-relationshipsがあります。これは、結合クエリの実行を支援します。

import Dexie from 'dexie' 
import relationships from 'dexie-relationships' 

class OrdersDB extends Dexie { 
    customers: Dexie.Table<Customer, string>; 
    products: Dexie.Table<Producs, string>; 
    pricesPerCustomer: Dexie.Table<PricePerCustomer, string>; 
    orders: Dexie.Table<Order, string>; 

    constructor() { 
    super ("OrdersDB", {addons: [relationships]}); 
    this.version(1).stores({ 
     customers: 'id, name', 
     products: 'id, name', 
     pricesPerCustomer: ` 
     id, 
     customerId -> customers.id, 
     productId -> products.id, 
     [customerId+productId]`, // Optimizes compound query (see below) 
     orders: ` 
     id, 
     customerId -> customers.id, 
     productId -> products.id` 
    }); 
    } 
} 

interface Customer { 
    id: string; 
    name: string; 
    orders?: Order[]; // db.customers.with({orders: 'orders'}) 
    prices?: PricesPerCustomer[]; // with({prices: 'pricesPerCustomer'}) 
} 

interface Product { 
    id: string; 
    name: string; 
    prices?: PricesPerCustomer[]; // with({prices: 'pricesPerCustomer'}) 
} 

interface PricePerCustomer { 
    id: string; 
    price: number; 
    currency: string; 
    customerId: string; 
    customer?: Customer; // with({customer: 'customerId'}) 
    productId: string; 
    product?: Product; // with({product: 'productId'}) 
} 

interface Order { 
    id: string; 
    customerId: string; 
    customer?: Customer; // with({customer: 'customerId'}) 
    productId: string; 
    product?: Product; // with({product: 'productId'}) 
    quantity: number; 
    price?: number; // When returned from getOrders() below. 
    currency?: string; // --"-- 
} 


const db = new OrdersDB(); 

/* Returns array of Customer with the "orders" and "prices" arrays attached. 
*/ 
async function getCustomersBeginningWithA() { 
    return await db.customers.where('name').startsWithIgnoreCase('a') 
    .with({orders: 'orders', prices: 'pricesPerCustomer'}); 
} 

/* Returns the price for a certain customer and product using 
    a compound query (Must use Dexie 2.0 for this). The query is 
    optimized if having a compound index ['customerId+productId'] 
    declared in the database schema (as done above). 
*/ 
async function getPrice (customerId: string, productId: string) { 
    return await db.pricesPerCustomer.get({ 
    customerId: customerId, 
    productId: productId 
    }); 
} 

async function getOrders (customerId: string) { 
    // Load orders for given customer with product property set. 
    const orders = await db.orders.where({customerId: customerId}) 
    .with({product: 'productId'}); 

    // Load prices for this each customer/product 
    const prices = await Promise.all(orders.map(order => 
    getPrice(customerId, order.id))); 

    // Return orders with price and currency properties set: 
    return orders.map((order, idx) => { 
    const pricePerCustomer = prices[idx]; 
    return { 
     ...order, 
     price: pricePerCustomer.price, 
     currency: pricePerCustomer.currency 
    }; 
    }); 
} 

各プライマリキーを文字列として宣言しているので、各キーを手動で作成する必要があります。スキーマ宣言で自動生成された数字も使用していた可能性があります( "id、..."の代わりに "++ id、..."を使用)。その場合は、テーブルをDexie.Table <顧客、番号>の代わりにDexie.Table <の顧客、文字列>の代わりに宣言します。

+0

Davidさん、ありがとうございました。たとえば、1000レコードのテーブルと200.000レコード以上の第2テーブルを結合しなければならないのですか? – DarioN1

+1

サンプル内の各クエリは、インデックスを最適な方法で使用します。フルテーブルスキャンなどはありません。正確なパフォーマンスを得るには、測定する必要があります。 –

+1

パフォーマンス番号が表示された場合は、お気軽にお問い合わせください。また、サンプルに問題が見つかった場合(コンパイル/テストされていないため) –

関連する問題