IndexedDB - 存储大量数据的正确方法
IndexedDB - Correct way to store big amount of data
我必须实现一个使用 LocalDB 来管理离线订单创建的 Web 应用程序。
此刻我正在使用 Dexie 实现 LocalDB Angular2/Typescript。
我要做的是实现一个数据库,以便能够管理:
- 客户(+1000 条记录)
- 产品(+2000 条记录)
- 产品
- 每个客户定义的价格 +(100.000 条记录)
- 订单(少量数据)
等...
它必须管理大量数据,因为产品、客户和价格很多或记录...
我的问题是:
如果我必须使用像 SQL SERVER 或 MySql 这样的通用关系数据库来实现这个数据库,
当我编写临时订单时,我存储了 idMaterial 和数量...
但是我必须在 IndexedDB 中做什么?
最好像 mySql/SqlServer 那样使用 idMaterial/Qty 存储临时订单并检索信息
通过执行 INNER JOIN 或更好地存储在本地 table Products/Prices 的所有信息来获取产品(在需要时)
为了避免 INNER JOIN 查询 ?
我可以 运行 INNER JOIN between tables 加入 2000 多种产品和 100.000 产品价格定义每个客户吗?
感谢支持!
IndexedDB 的架构很像 SQL 数据库,因为它有表、行和事务,尽管它们的名称不同(Table = ObjectStore,行 = Object)。
使用 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。
我必须实现一个使用 LocalDB 来管理离线订单创建的 Web 应用程序。
此刻我正在使用 Dexie 实现 LocalDB Angular2/Typescript。
我要做的是实现一个数据库,以便能够管理:
- 客户(+1000 条记录)
- 产品(+2000 条记录)
- 产品
- 每个客户定义的价格 +(100.000 条记录)
- 订单(少量数据)
等...
它必须管理大量数据,因为产品、客户和价格很多或记录...
我的问题是:
如果我必须使用像 SQL SERVER 或 MySql 这样的通用关系数据库来实现这个数据库, 当我编写临时订单时,我存储了 idMaterial 和数量...
但是我必须在 IndexedDB 中做什么?
最好像 mySql/SqlServer 那样使用 idMaterial/Qty 存储临时订单并检索信息 通过执行 INNER JOIN 或更好地存储在本地 table Products/Prices 的所有信息来获取产品(在需要时) 为了避免 INNER JOIN 查询 ?
我可以 运行 INNER JOIN between tables 加入 2000 多种产品和 100.000 产品价格定义每个客户吗?
感谢支持!
IndexedDB 的架构很像 SQL 数据库,因为它有表、行和事务,尽管它们的名称不同(Table = ObjectStore,行 = Object)。
使用 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