Model Management
The model.load() method is the primary way to sync dimension table structure and data from external sources into Farseer.
Basic Usage
import { ModelTableColumnType } from 'farseer-client';
await client.model.load({
model: {
tables: [{
name: 'Product',
columns: [
{ name: 'Name', type: ModelTableColumnType.PrimaryKey },
{ name: 'Description', type: ModelTableColumnType.Description },
{ name: 'Category', type: ModelTableColumnType.ForeignKey, foreignKeyTableName: 'Category' }
],
rows: [
['Product A', 'Description A', 'Electronics'],
['Product B', 'Description B', 'Furniture']
]
}],
variables: [],
dependencies: { tables: [], members: [], variables: [] }
},
options: {
clear: false,
deleteEnabled: { rows: false, tables: false, variables: false, columns: false, cells: false },
dryRun: false
}
});
Column Types
| Type | Purpose | Example |
|---|---|---|
PrimaryKey | Unique identifier for the member | Product name |
Description | Display description | Product details |
ForeignKey | Reference to another dimension table | Category |
Formula | Calculated expression | sum(...) |
Number | Numeric property | Price |
Text | Text property | Notes |
Date | Date property | Created date |
Options
| Option | Type | Description |
|---|---|---|
clear | boolean | Clear existing data before loading |
dryRun | boolean | Preview changes without applying |
deleteEnabled.rows | boolean | Allow deleting dimension members |
deleteEnabled.tables | boolean | Allow deleting dimension tables |
deleteEnabled.variables | boolean | Allow deleting variables |
deleteEnabled.columns | boolean | Allow deleting columns |
deleteEnabled.cells | boolean | Allow deleting cell data |
tip
Use dryRun: true during development to preview what changes would be made without actually applying them.
Syncing Multiple Tables
Use data.syncMultipleTables() for a simplified interface when syncing Arquero tables:
await client.data.syncMultipleTables([
{
name: 'Products',
columns: [
{ name: 'Name', type: 'PrimaryKey' },
{ name: 'Category', type: 'ForeignKey', foreignKeyTableName: 'Categories' }
],
rows: productTable // Arquero table
},
{
name: 'Categories',
columns: [
{ name: 'Name', type: 'PrimaryKey' },
{ name: 'Description', type: 'Description' }
],
rows: categoryTable
}
]);
Batch Processing for Large Datasets
For large datasets, process in batches to avoid memory and timeout issues:
const allRows = [...]; // e.g., 10,000 dimension members
const batchSize = 5000;
for (let i = 0; i < allRows.length; i += batchSize) {
const batchRows = allRows.slice(i, i + batchSize);
await client.model.load({
model: {
tables: [{
name: 'Product',
columns: [
{ name: 'Name', type: ModelTableColumnType.PrimaryKey },
{ name: 'Description', type: ModelTableColumnType.Description },
],
rows: batchRows
}],
variables: [],
dependencies: { tables: [], members: [], variables: [] }
},
options: {
clear: i === 0, // Only clear on first batch
deleteEnabled: { rows: false, tables: false, variables: false, columns: false, cells: false },
dryRun: false
}
});
console.log(`Synced ${Math.min(i + batchSize, allRows.length)} / ${allRows.length} members`);
}
SQL Server to Farseer Sync
A common real-world pattern: read from SQL Server and sync to Farseer.
import * as mssql from 'mssql';
import * as farseer from 'farseer-client';
const client = new farseer.FarseerClient();
const pool = await mssql.connect({
user: 'username',
password: 'password',
server: 'server',
database: 'database',
});
// Query data
const data = await client.data.mssqlQuery(pool, `
SELECT * FROM [dbo].[Products]
WHERE Active = 1
`);
// Select relevant columns and sync
const brickData = data.select('RegionId', 'AreaId');
await client.data.syncMultipleTables([
{
name: 'Brick',
columns: [
{ name: 'regionId', type: farseer.ModelTableColumnType.PrimaryKey },
{ name: 'areaId', type: farseer.ModelTableColumnType.ForeignKey, foreignKeyTableName: 'Area' },
],
rows: brickData,
}
]);
await pool.close();