feat: join node

This commit is contained in:
root 2020-05-16 23:11:34 -05:00
parent 0e491bd762
commit 10b7447f7d
3 changed files with 180 additions and 1 deletions

View File

@ -0,0 +1,80 @@
import Node from '../Node.js'
class JoinNode extends Node {
constructor (props) {
super(props)
this._assignProps(props)
}
export = () => {
const baseTable = this.tables.find(t => t.label === this.baseTableLabel)
const baseTableRows = baseTable.getRows()
const tablesToJoin = this.tables.filter(t => {
return t.label !== this.baseTableLabel
})
const relatedTables = this.joinParams.map(joinParam => {
const foreignTable = tablesToJoin.find(t => {
return t.label === joinParam.foreignTable
})
const foreignTableRows = foreignTable.getRows()
const mergedRows = baseTableRows.map(baseRow => {
const matchingForeignRow = foreignTableRows.find(foreignRow => {
return baseRow[joinParam.primaryTableKey] === foreignRow[joinParam.matchingKey]
})
let rowToMerge = {}
for (let key in matchingForeignRow) {
rowToMerge[`${joinParam.foreignTable}::${key}`] = matchingForeignRow[key]
}
return {...baseRow, ...rowToMerge}
})
return mergedRows
})
return relatedTables[0]
}
setJoinBy = joinBy => {
const joinByValidation = this._validateJoinBy(joinBy)
if (joinByValidation.status === 'ERR') throw joinByValidation
else {
this.baseTableLabel = joinBy.baseTableLabel
this.joinParams = joinBy.joinParams
}
}
_assignProps = props => {
if (props.joinBy) this.setJoinBy(props.joinBy)
}
_validateJoinBy = joinBy => {
const err = {
status: 'ERR',
error: {
label: 'JoinBy Parameters are not valid',
messages: []
}
}
const { baseTableLabel, joinParams } = joinBy
if (!baseTableLabel) err.error.messages.push('No baseTableLabel provided')
if (!Array.isArray(joinParams)) {
const joinParamsType = typeof joinParams
err.error.messages.push(`Keys was of type ${joinParamsType} should be an array`)
return err
}
for (let p = 0; p < joinParams.length; p++) {
if (typeof joinParams[p] !== 'object') err.error.messages.push(`joinParams[${p}] is not an object`)
}
if (err.error.messages.length > 0) return err
else return { status: 'OK' }
}
}
export default JoinNode

View File

@ -0,0 +1,97 @@
import JoinNode from '../../../core/entities/nodes/JoinNode.js'
import Table from '../../../core/entities/Table.js'
const joinTables = () => {
const pickupTable = new Table({
id: 'abc',
label: 'receipts',
rows: [
{ id: '2345676', contractor: 'AshBritt', type: 'row', lat: 54, long: 31 },
{ id: '2345676', contractor: 'Jefferson',type: 'lh', lat: 31, long: -71.34 },
{ id: '2345676', contractor: 'AshBritt', type: 'lh', lat: 80, long: -41 },
]
})
const contractorTable = new Table({
id: 'XYZ',
label: 'contractors',
rows: [
{ id: '1WE3V6', name: 'AshBritt', employeeCount: 43, homeState: 'CA' },
{ id: 'FG4S67', name: 'Jefferson', employeeCount: 91, homeState: 'AL' }
]
})
const expectedOutput = [
{ id: '2345676', contractor: 'AshBritt', type: 'row', lat: 54, long: 31, 'contractors::id': '1WE3V6', 'contractors::name': 'AshBritt', 'contractors::employeeCount': 43, 'contractors::homeState': 'CA' },
{ id: '2345676', contractor: 'Jefferson',type: 'lh', lat: 31, long: -71.34, 'contractors::id': 'FG4S67', 'contractors::name': 'Jefferson', 'contractors::employeeCount': 91, 'contractors::homeState': 'AL' },
{ id: '2345676', contractor: 'AshBritt', type: 'lh', lat: 80, long: -41, 'contractors::id': '1WE3V6', 'contractors::name': 'AshBritt', 'contractors::employeeCount': 43, 'contractors::homeState': 'CA' },
]
const joinNode = new JoinNode({
id: 'QWE',
label: 'Receipts with Contractors',
tables: [pickupTable, contractorTable],
joinBy: {
baseTableLabel: 'receipts',
joinParams: [
{ foreignTable: 'contractors', primaryTableKey: 'contractor', matchingKey: 'name' }
]
}
})
const joinNodeProps = joinNode.export()
if (JSON.stringify(joinNodeProps) === JSON.stringify(expectedOutput)) return true
else return false
}
const setJoinBy = () => {
const pickupTable = new Table({
id: 'abc',
label: 'receipts',
rows: [
{ id: '2345676', contractor: 'AshBritt', type: 'row', lat: 54, long: 31 },
{ id: '2345676', contractor: 'Jefferson',type: 'lh', lat: 31, long: -71.34 },
{ id: '2345676', contractor: 'AshBritt', type: 'lh', lat: 80, long: -41 },
]
})
const contractorTable = new Table({
id: 'XYZ',
label: 'contractors',
rows: [
{ id: '1WE3V6', name: 'AshBritt', employeeCount: 43, homeState: 'CA' },
{ id: 'FG4S67', name: 'Jefferson', employeeCount: 91, homeState: 'AL' }
]
})
const expectedOutput = [
{ id: '2345676', contractor: 'AshBritt', type: 'row', lat: 54, long: 31, 'contractors::id': '1WE3V6', 'contractors::name': 'AshBritt', 'contractors::employeeCount': 43, 'contractors::homeState': 'CA' },
{ id: '2345676', contractor: 'Jefferson',type: 'lh', lat: 31, long: -71.34, 'contractors::id': 'FG4S67', 'contractors::name': 'Jefferson', 'contractors::employeeCount': 91, 'contractors::homeState': 'AL' },
{ id: '2345676', contractor: 'AshBritt', type: 'lh', lat: 80, long: -41, 'contractors::id': '1WE3V6', 'contractors::name': 'AshBritt', 'contractors::employeeCount': 43, 'contractors::homeState': 'CA' },
]
const joinNode = new JoinNode({
id: 'QWE',
label: 'Receipts with Contractors',
tables: [pickupTable, contractorTable]
})
joinNode.setJoinBy({
baseTableLabel: 'receipts',
joinParams: [
{ foreignTable: 'contractors', primaryTableKey: 'contractor', matchingKey: 'name' }
]
})
const joinNodeProps = joinNode.export()
if (JSON.stringify(joinNodeProps) === JSON.stringify(expectedOutput)) return true
else return false
}
export default [
{ name: 'Entity | Join Table Test', test: joinTables },
{ name: 'Entity | Join Table setJoinBy', test: setJoinBy },
]

View File

@ -3,6 +3,7 @@ import ProgressBar from 'progress'
import tableTests from '../tests/core/tableTests.js'
import nodeTests from '../tests/core/nodeTests.js'
import filterNodeTests from '../tests/core/nodes/filterNodeTests.js'
import joinNodeTests from '../tests/core/nodes/joinNodeTests.js'
function runTestsAndReturnFailures (tests) {
const testTotalCount = tests.length
@ -39,7 +40,8 @@ function init (tests) {
const testsArray = [
tableTests,
nodeTests,
filterNodeTests
filterNodeTests,
joinNodeTests
]
init (testsArray.flat())