@nshiab/simple-data-analysis-core 2.0.9 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/class/SDAError.d.ts +6 -6
- package/esm/class/SDAError.js +6 -6
- package/esm/class/Simple.d.ts +9 -9
- package/esm/class/Simple.js +9 -9
- package/esm/class/SimpleDB.d.ts +80 -76
- package/esm/class/SimpleDB.d.ts.map +1 -1
- package/esm/class/SimpleDB.js +80 -76
- package/esm/class/SimpleTable.d.ts +2806 -1139
- package/esm/class/SimpleTable.d.ts.map +1 -1
- package/esm/class/SimpleTable.js +2792 -1149
- package/esm/helpers/buildApproximateMutualReachabilityMst.d.ts +45 -0
- package/esm/helpers/buildApproximateMutualReachabilityMst.d.ts.map +1 -0
- package/esm/helpers/buildApproximateMutualReachabilityMst.js +212 -0
- package/esm/helpers/buildChronologicalGraphComponentsSql.d.ts +14 -0
- package/esm/helpers/buildChronologicalGraphComponentsSql.d.ts.map +1 -0
- package/esm/helpers/buildChronologicalGraphComponentsSql.js +167 -0
- package/esm/helpers/buildExactMutualReachabilityMst.d.ts +28 -0
- package/esm/helpers/buildExactMutualReachabilityMst.d.ts.map +1 -0
- package/esm/helpers/buildExactMutualReachabilityMst.js +97 -0
- package/esm/helpers/buildGraphTemporalCostStateSql.d.ts +12 -0
- package/esm/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -0
- package/esm/helpers/buildGraphTemporalCostStateSql.js +86 -0
- package/esm/helpers/buildGraphTemporalReachabilitySql.d.ts +13 -0
- package/esm/helpers/buildGraphTemporalReachabilitySql.d.ts.map +1 -0
- package/esm/helpers/buildGraphTemporalReachabilitySql.js +70 -0
- package/esm/helpers/buildSparseMutualReachabilityMst.d.ts +10 -0
- package/esm/helpers/buildSparseMutualReachabilityMst.d.ts.map +1 -0
- package/esm/helpers/buildSparseMutualReachabilityMst.js +47 -0
- package/esm/helpers/buildUmapGraph.d.ts +2 -5
- package/esm/helpers/buildUmapGraph.d.ts.map +1 -1
- package/esm/helpers/buildUmapGraph.js +6 -100
- package/esm/helpers/buildVectorNeighbors.d.ts +45 -0
- package/esm/helpers/buildVectorNeighbors.d.ts.map +1 -0
- package/esm/helpers/buildVectorNeighbors.js +170 -0
- package/esm/helpers/buildWeakGraphComponentsSql.d.ts +3 -0
- package/esm/helpers/buildWeakGraphComponentsSql.d.ts.map +1 -0
- package/esm/helpers/buildWeakGraphComponentsSql.js +32 -0
- package/esm/helpers/camelCase.d.ts +7 -5
- package/esm/helpers/camelCase.d.ts.map +1 -1
- package/esm/helpers/camelCase.js +7 -5
- package/esm/helpers/capitalize.d.ts +6 -4
- package/esm/helpers/capitalize.d.ts.map +1 -1
- package/esm/helpers/capitalize.js +6 -4
- package/esm/helpers/clusterHdbscan.d.ts +18 -0
- package/esm/helpers/clusterHdbscan.d.ts.map +1 -0
- package/esm/helpers/clusterHdbscan.js +342 -0
- package/esm/helpers/computeCovariance.d.ts +16 -0
- package/esm/helpers/computeCovariance.d.ts.map +1 -0
- package/esm/helpers/computeCovariance.js +99 -0
- package/esm/helpers/computeMahalanobisDistances.d.ts +14 -0
- package/esm/helpers/computeMahalanobisDistances.d.ts.map +1 -0
- package/esm/helpers/computeMahalanobisDistances.js +87 -0
- package/esm/helpers/createDirectory.d.ts +4 -3
- package/esm/helpers/createDirectory.d.ts.map +1 -1
- package/esm/helpers/createDirectory.js +4 -3
- package/esm/helpers/dataToArrays.d.ts +6 -4
- package/esm/helpers/dataToArrays.d.ts.map +1 -1
- package/esm/helpers/dataToArrays.js +6 -4
- package/esm/helpers/extractTypes.d.ts +1 -1
- package/esm/helpers/extractTypes.js +4 -9
- package/esm/helpers/factorCovariance.d.ts +17 -0
- package/esm/helpers/factorCovariance.d.ts.map +1 -0
- package/esm/helpers/factorCovariance.js +189 -0
- package/esm/helpers/findGeoColumn.d.ts +6 -4
- package/esm/helpers/findGeoColumn.d.ts.map +1 -1
- package/esm/helpers/findGeoColumn.js +6 -4
- package/esm/helpers/findGeoColumnFromSchema.d.ts +8 -5
- package/esm/helpers/findGeoColumnFromSchema.d.ts.map +1 -1
- package/esm/helpers/findGeoColumnFromSchema.js +8 -5
- package/esm/helpers/formatDate.d.ts +12 -6
- package/esm/helpers/formatDate.d.ts.map +1 -1
- package/esm/helpers/formatDate.js +12 -6
- package/esm/helpers/formatMissingTables.d.ts +8 -5
- package/esm/helpers/formatMissingTables.d.ts.map +1 -1
- package/esm/helpers/formatMissingTables.js +8 -5
- package/esm/helpers/formatNumber.d.ts +19 -10
- package/esm/helpers/formatNumber.d.ts.map +1 -1
- package/esm/helpers/formatNumber.js +32 -17
- package/esm/helpers/getGraphEdgeIdColumn.d.ts +9 -0
- package/esm/helpers/getGraphEdgeIdColumn.d.ts.map +1 -0
- package/esm/helpers/getGraphEdgeIdColumn.js +25 -0
- package/esm/helpers/getGraphEndpointColumns.d.ts +11 -0
- package/esm/helpers/getGraphEndpointColumns.d.ts.map +1 -0
- package/esm/helpers/getGraphEndpointColumns.js +160 -0
- package/esm/helpers/getGraphWeightColumn.d.ts +10 -0
- package/esm/helpers/getGraphWeightColumn.d.ts.map +1 -0
- package/esm/helpers/getGraphWeightColumn.js +40 -0
- package/esm/helpers/graphRouteResultSchema.d.ts +4 -0
- package/esm/helpers/graphRouteResultSchema.d.ts.map +1 -0
- package/esm/helpers/graphRouteResultSchema.js +12 -0
- package/esm/helpers/graphRouteResultSelect.d.ts +4 -0
- package/esm/helpers/graphRouteResultSelect.d.ts.map +1 -0
- package/esm/helpers/graphRouteResultSelect.js +22 -0
- package/esm/helpers/hasGeometryColumn.d.ts +4 -3
- package/esm/helpers/hasGeometryColumn.d.ts.map +1 -1
- package/esm/helpers/hasGeometryColumn.js +4 -3
- package/esm/helpers/inspectGraphConnectivity.d.ts +10 -0
- package/esm/helpers/inspectGraphConnectivity.d.ts.map +1 -0
- package/esm/helpers/inspectGraphConnectivity.js +55 -0
- package/esm/helpers/mergeOptions.d.ts +24 -13
- package/esm/helpers/mergeOptions.d.ts.map +1 -1
- package/esm/helpers/mergeOptions.js +24 -13
- package/esm/helpers/parseValue.d.ts +6 -4
- package/esm/helpers/parseValue.d.ts.map +1 -1
- package/esm/helpers/parseValue.js +6 -4
- package/esm/helpers/prepareGraphRouteSql.d.ts +31 -0
- package/esm/helpers/prepareGraphRouteSql.d.ts.map +1 -0
- package/esm/helpers/prepareGraphRouteSql.js +86 -0
- package/esm/helpers/prepareGraphStarts.d.ts +9 -0
- package/esm/helpers/prepareGraphStarts.d.ts.map +1 -0
- package/esm/helpers/prepareGraphStarts.js +68 -0
- package/esm/helpers/prepareGraphTemporalSql.d.ts +28 -0
- package/esm/helpers/prepareGraphTemporalSql.d.ts.map +1 -0
- package/esm/helpers/prepareGraphTemporalSql.js +154 -0
- package/esm/helpers/prepareGraphTraversal.d.ts +19 -0
- package/esm/helpers/prepareGraphTraversal.d.ts.map +1 -0
- package/esm/helpers/prepareGraphTraversal.js +79 -0
- package/esm/helpers/prepareNumericFeatures.d.ts +41 -0
- package/esm/helpers/prepareNumericFeatures.d.ts.map +1 -0
- package/esm/helpers/prepareNumericFeatures.js +210 -0
- package/esm/helpers/prettyDuration.d.ts +14 -8
- package/esm/helpers/prettyDuration.d.ts.map +1 -1
- package/esm/helpers/prettyDuration.js +14 -8
- package/esm/helpers/printTable.d.ts +18 -13
- package/esm/helpers/printTable.d.ts.map +1 -1
- package/esm/helpers/printTable.js +18 -13
- package/esm/helpers/publishPreparedColumns.d.ts +37 -0
- package/esm/helpers/publishPreparedColumns.d.ts.map +1 -0
- package/esm/helpers/publishPreparedColumns.js +113 -0
- package/esm/helpers/queryDB.d.ts +24 -13
- package/esm/helpers/queryDB.d.ts.map +1 -1
- package/esm/helpers/queryDB.js +24 -13
- package/esm/helpers/queueAsyncBarrier.d.ts +12 -7
- package/esm/helpers/queueAsyncBarrier.d.ts.map +1 -1
- package/esm/helpers/queueAsyncBarrier.js +12 -7
- package/esm/helpers/queueGraphResult.d.ts +18 -0
- package/esm/helpers/queueGraphResult.d.ts.map +1 -0
- package/esm/helpers/queueGraphResult.js +39 -0
- package/esm/helpers/quoteIdentifier.d.ts +4 -3
- package/esm/helpers/quoteIdentifier.d.ts.map +1 -1
- package/esm/helpers/quoteIdentifier.js +4 -3
- package/esm/helpers/quoteQualifiedIdentifier.d.ts +6 -4
- package/esm/helpers/quoteQualifiedIdentifier.d.ts.map +1 -1
- package/esm/helpers/quoteQualifiedIdentifier.js +6 -4
- package/esm/helpers/runQuery.d.ts.map +1 -1
- package/esm/helpers/runQuery.js +17 -3
- package/esm/helpers/selectFuzzyReplacements.d.ts +11 -0
- package/esm/helpers/selectFuzzyReplacements.d.ts.map +1 -0
- package/esm/helpers/selectFuzzyReplacements.js +124 -0
- package/esm/helpers/stabilizeCosineVectors.d.ts +14 -0
- package/esm/helpers/stabilizeCosineVectors.d.ts.map +1 -0
- package/esm/helpers/stabilizeCosineVectors.js +34 -0
- package/esm/helpers/stringToArray.d.ts +4 -3
- package/esm/helpers/stringToArray.d.ts.map +1 -1
- package/esm/helpers/stringToArray.js +4 -3
- package/esm/helpers/updateColumnsWithJS.d.ts +12 -6
- package/esm/helpers/updateColumnsWithJS.d.ts.map +1 -1
- package/esm/helpers/updateColumnsWithJS.js +12 -6
- package/esm/helpers/validateGraphRouteResultSchema.d.ts +4 -0
- package/esm/helpers/validateGraphRouteResultSchema.d.ts.map +1 -0
- package/esm/helpers/validateGraphRouteResultSchema.js +13 -0
- package/esm/helpers/validateGraphTemporalEvents.d.ts +7 -0
- package/esm/helpers/validateGraphTemporalEvents.d.ts.map +1 -0
- package/esm/helpers/validateGraphTemporalEvents.js +47 -0
- package/esm/helpers/validateNumericalAnalysis.d.ts +10 -6
- package/esm/helpers/validateNumericalAnalysis.d.ts.map +1 -1
- package/esm/helpers/validateNumericalAnalysis.js +10 -6
- package/esm/helpers/validateVectorRowIds.d.ts +4 -0
- package/esm/helpers/validateVectorRowIds.d.ts.map +1 -0
- package/esm/helpers/validateVectorRowIds.js +16 -0
- package/esm/helpers/vectorDistanceExpression.d.ts +6 -0
- package/esm/helpers/vectorDistanceExpression.d.ts.map +1 -0
- package/esm/helpers/vectorDistanceExpression.js +11 -0
- package/esm/helpers/wrapString.d.ts +10 -7
- package/esm/helpers/wrapString.d.ts.map +1 -1
- package/esm/helpers/wrapString.js +10 -7
- package/esm/methods/addId.d.ts +5 -0
- package/esm/methods/addId.d.ts.map +1 -0
- package/esm/methods/addId.js +38 -0
- package/esm/methods/commonNeighbors.d.ts +10 -0
- package/esm/methods/commonNeighbors.d.ts.map +1 -0
- package/esm/methods/commonNeighbors.js +101 -0
- package/esm/methods/connectedComponents.d.ts +9 -0
- package/esm/methods/connectedComponents.d.ts.map +1 -0
- package/esm/methods/connectedComponents.js +147 -0
- package/esm/methods/degree.d.ts +9 -0
- package/esm/methods/degree.d.ts.map +1 -0
- package/esm/methods/degree.js +135 -0
- package/esm/methods/distances.d.ts +12 -0
- package/esm/methods/distances.d.ts.map +1 -0
- package/esm/methods/distances.js +164 -0
- package/esm/methods/findCycles.d.ts +12 -0
- package/esm/methods/findCycles.d.ts.map +1 -0
- package/esm/methods/findCycles.js +330 -0
- package/esm/methods/fuzzyClean.d.ts.map +1 -1
- package/esm/methods/fuzzyClean.js +17 -136
- package/esm/methods/fuzzyJoin.js +70 -16
- package/esm/methods/getTypes.d.ts +1 -1
- package/esm/methods/hdbscan.d.ts +5 -0
- package/esm/methods/hdbscan.d.ts.map +1 -0
- package/esm/methods/hdbscan.js +208 -0
- package/esm/methods/mahalanobis.d.ts +5 -0
- package/esm/methods/mahalanobis.d.ts.map +1 -0
- package/esm/methods/mahalanobis.js +92 -0
- package/esm/methods/neighbors.d.ts +9 -0
- package/esm/methods/neighbors.d.ts.map +1 -0
- package/esm/methods/neighbors.js +81 -0
- package/esm/methods/normalizeVector.d.ts +5 -0
- package/esm/methods/normalizeVector.d.ts.map +1 -0
- package/esm/methods/normalizeVector.js +132 -0
- package/esm/methods/paths.d.ts +12 -0
- package/esm/methods/paths.d.ts.map +1 -0
- package/esm/methods/paths.js +287 -0
- package/esm/methods/reachable.d.ts +11 -0
- package/esm/methods/reachable.d.ts.map +1 -0
- package/esm/methods/reachable.js +131 -0
- package/esm/methods/rowToVector.d.ts +5 -0
- package/esm/methods/rowToVector.d.ts.map +1 -0
- package/esm/methods/rowToVector.js +77 -0
- package/esm/methods/shortestPath.d.ts +12 -0
- package/esm/methods/shortestPath.d.ts.map +1 -0
- package/esm/methods/shortestPath.js +337 -0
- package/esm/methods/topologicalSort.d.ts +7 -0
- package/esm/methods/topologicalSort.d.ts.map +1 -0
- package/esm/methods/topologicalSort.js +164 -0
- package/esm/methods/trim.d.ts +1 -1
- package/esm/methods/trim.d.ts.map +1 -1
- package/esm/methods/trim.js +17 -8
- package/llm.md +2146 -173
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/script/class/SDAError.d.ts +6 -6
- package/script/class/SDAError.js +6 -6
- package/script/class/Simple.d.ts +9 -9
- package/script/class/Simple.js +9 -9
- package/script/class/SimpleDB.d.ts +80 -76
- package/script/class/SimpleDB.d.ts.map +1 -1
- package/script/class/SimpleDB.js +80 -76
- package/script/class/SimpleTable.d.ts +2806 -1139
- package/script/class/SimpleTable.d.ts.map +1 -1
- package/script/class/SimpleTable.js +2792 -1149
- package/script/helpers/buildApproximateMutualReachabilityMst.d.ts +45 -0
- package/script/helpers/buildApproximateMutualReachabilityMst.d.ts.map +1 -0
- package/script/helpers/buildApproximateMutualReachabilityMst.js +219 -0
- package/script/helpers/buildChronologicalGraphComponentsSql.d.ts +14 -0
- package/script/helpers/buildChronologicalGraphComponentsSql.d.ts.map +1 -0
- package/script/helpers/buildChronologicalGraphComponentsSql.js +174 -0
- package/script/helpers/buildExactMutualReachabilityMst.d.ts +28 -0
- package/script/helpers/buildExactMutualReachabilityMst.d.ts.map +1 -0
- package/script/helpers/buildExactMutualReachabilityMst.js +103 -0
- package/script/helpers/buildGraphTemporalCostStateSql.d.ts +12 -0
- package/script/helpers/buildGraphTemporalCostStateSql.d.ts.map +1 -0
- package/script/helpers/buildGraphTemporalCostStateSql.js +92 -0
- package/script/helpers/buildGraphTemporalReachabilitySql.d.ts +13 -0
- package/script/helpers/buildGraphTemporalReachabilitySql.d.ts.map +1 -0
- package/script/helpers/buildGraphTemporalReachabilitySql.js +76 -0
- package/script/helpers/buildSparseMutualReachabilityMst.d.ts +10 -0
- package/script/helpers/buildSparseMutualReachabilityMst.d.ts.map +1 -0
- package/script/helpers/buildSparseMutualReachabilityMst.js +50 -0
- package/script/helpers/buildUmapGraph.d.ts +2 -5
- package/script/helpers/buildUmapGraph.d.ts.map +1 -1
- package/script/helpers/buildUmapGraph.js +6 -100
- package/script/helpers/buildVectorNeighbors.d.ts +45 -0
- package/script/helpers/buildVectorNeighbors.d.ts.map +1 -0
- package/script/helpers/buildVectorNeighbors.js +176 -0
- package/script/helpers/buildWeakGraphComponentsSql.d.ts +3 -0
- package/script/helpers/buildWeakGraphComponentsSql.d.ts.map +1 -0
- package/script/helpers/buildWeakGraphComponentsSql.js +38 -0
- package/script/helpers/camelCase.d.ts +7 -5
- package/script/helpers/camelCase.d.ts.map +1 -1
- package/script/helpers/camelCase.js +7 -5
- package/script/helpers/capitalize.d.ts +6 -4
- package/script/helpers/capitalize.d.ts.map +1 -1
- package/script/helpers/capitalize.js +6 -4
- package/script/helpers/clusterHdbscan.d.ts +18 -0
- package/script/helpers/clusterHdbscan.d.ts.map +1 -0
- package/script/helpers/clusterHdbscan.js +346 -0
- package/script/helpers/computeCovariance.d.ts +16 -0
- package/script/helpers/computeCovariance.d.ts.map +1 -0
- package/script/helpers/computeCovariance.js +105 -0
- package/script/helpers/computeMahalanobisDistances.d.ts +14 -0
- package/script/helpers/computeMahalanobisDistances.d.ts.map +1 -0
- package/script/helpers/computeMahalanobisDistances.js +93 -0
- package/script/helpers/createDirectory.d.ts +4 -3
- package/script/helpers/createDirectory.d.ts.map +1 -1
- package/script/helpers/createDirectory.js +4 -3
- package/script/helpers/dataToArrays.d.ts +6 -4
- package/script/helpers/dataToArrays.d.ts.map +1 -1
- package/script/helpers/dataToArrays.js +6 -4
- package/script/helpers/extractTypes.d.ts +1 -1
- package/script/helpers/extractTypes.js +4 -9
- package/script/helpers/factorCovariance.d.ts +17 -0
- package/script/helpers/factorCovariance.d.ts.map +1 -0
- package/script/helpers/factorCovariance.js +194 -0
- package/script/helpers/findGeoColumn.d.ts +6 -4
- package/script/helpers/findGeoColumn.d.ts.map +1 -1
- package/script/helpers/findGeoColumn.js +6 -4
- package/script/helpers/findGeoColumnFromSchema.d.ts +8 -5
- package/script/helpers/findGeoColumnFromSchema.d.ts.map +1 -1
- package/script/helpers/findGeoColumnFromSchema.js +8 -5
- package/script/helpers/formatDate.d.ts +12 -6
- package/script/helpers/formatDate.d.ts.map +1 -1
- package/script/helpers/formatDate.js +12 -6
- package/script/helpers/formatMissingTables.d.ts +8 -5
- package/script/helpers/formatMissingTables.d.ts.map +1 -1
- package/script/helpers/formatMissingTables.js +8 -5
- package/script/helpers/formatNumber.d.ts +19 -10
- package/script/helpers/formatNumber.d.ts.map +1 -1
- package/script/helpers/formatNumber.js +32 -17
- package/script/helpers/getGraphEdgeIdColumn.d.ts +9 -0
- package/script/helpers/getGraphEdgeIdColumn.d.ts.map +1 -0
- package/script/helpers/getGraphEdgeIdColumn.js +31 -0
- package/script/helpers/getGraphEndpointColumns.d.ts +11 -0
- package/script/helpers/getGraphEndpointColumns.d.ts.map +1 -0
- package/script/helpers/getGraphEndpointColumns.js +166 -0
- package/script/helpers/getGraphWeightColumn.d.ts +10 -0
- package/script/helpers/getGraphWeightColumn.d.ts.map +1 -0
- package/script/helpers/getGraphWeightColumn.js +46 -0
- package/script/helpers/graphRouteResultSchema.d.ts +4 -0
- package/script/helpers/graphRouteResultSchema.d.ts.map +1 -0
- package/script/helpers/graphRouteResultSchema.js +18 -0
- package/script/helpers/graphRouteResultSelect.d.ts +4 -0
- package/script/helpers/graphRouteResultSelect.d.ts.map +1 -0
- package/script/helpers/graphRouteResultSelect.js +28 -0
- package/script/helpers/hasGeometryColumn.d.ts +4 -3
- package/script/helpers/hasGeometryColumn.d.ts.map +1 -1
- package/script/helpers/hasGeometryColumn.js +4 -3
- package/script/helpers/inspectGraphConnectivity.d.ts +10 -0
- package/script/helpers/inspectGraphConnectivity.d.ts.map +1 -0
- package/script/helpers/inspectGraphConnectivity.js +58 -0
- package/script/helpers/mergeOptions.d.ts +24 -13
- package/script/helpers/mergeOptions.d.ts.map +1 -1
- package/script/helpers/mergeOptions.js +24 -13
- package/script/helpers/parseValue.d.ts +6 -4
- package/script/helpers/parseValue.d.ts.map +1 -1
- package/script/helpers/parseValue.js +6 -4
- package/script/helpers/prepareGraphRouteSql.d.ts +31 -0
- package/script/helpers/prepareGraphRouteSql.d.ts.map +1 -0
- package/script/helpers/prepareGraphRouteSql.js +127 -0
- package/script/helpers/prepareGraphStarts.d.ts +9 -0
- package/script/helpers/prepareGraphStarts.d.ts.map +1 -0
- package/script/helpers/prepareGraphStarts.js +71 -0
- package/script/helpers/prepareGraphTemporalSql.d.ts +28 -0
- package/script/helpers/prepareGraphTemporalSql.d.ts.map +1 -0
- package/script/helpers/prepareGraphTemporalSql.js +161 -0
- package/script/helpers/prepareGraphTraversal.d.ts +19 -0
- package/script/helpers/prepareGraphTraversal.d.ts.map +1 -0
- package/script/helpers/prepareGraphTraversal.js +87 -0
- package/script/helpers/prepareNumericFeatures.d.ts +41 -0
- package/script/helpers/prepareNumericFeatures.d.ts.map +1 -0
- package/script/helpers/prepareNumericFeatures.js +217 -0
- package/script/helpers/prettyDuration.d.ts +14 -8
- package/script/helpers/prettyDuration.d.ts.map +1 -1
- package/script/helpers/prettyDuration.js +14 -8
- package/script/helpers/printTable.d.ts +18 -13
- package/script/helpers/printTable.d.ts.map +1 -1
- package/script/helpers/printTable.js +18 -13
- package/script/helpers/publishPreparedColumns.d.ts +37 -0
- package/script/helpers/publishPreparedColumns.d.ts.map +1 -0
- package/script/helpers/publishPreparedColumns.js +119 -0
- package/script/helpers/queryDB.d.ts +24 -13
- package/script/helpers/queryDB.d.ts.map +1 -1
- package/script/helpers/queryDB.js +24 -13
- package/script/helpers/queueAsyncBarrier.d.ts +12 -7
- package/script/helpers/queueAsyncBarrier.d.ts.map +1 -1
- package/script/helpers/queueAsyncBarrier.js +12 -7
- package/script/helpers/queueGraphResult.d.ts +18 -0
- package/script/helpers/queueGraphResult.d.ts.map +1 -0
- package/script/helpers/queueGraphResult.js +45 -0
- package/script/helpers/quoteIdentifier.d.ts +4 -3
- package/script/helpers/quoteIdentifier.d.ts.map +1 -1
- package/script/helpers/quoteIdentifier.js +4 -3
- package/script/helpers/quoteQualifiedIdentifier.d.ts +6 -4
- package/script/helpers/quoteQualifiedIdentifier.d.ts.map +1 -1
- package/script/helpers/quoteQualifiedIdentifier.js +6 -4
- package/script/helpers/runQuery.d.ts.map +1 -1
- package/script/helpers/runQuery.js +17 -3
- package/script/helpers/selectFuzzyReplacements.d.ts +11 -0
- package/script/helpers/selectFuzzyReplacements.d.ts.map +1 -0
- package/script/helpers/selectFuzzyReplacements.js +127 -0
- package/script/helpers/stabilizeCosineVectors.d.ts +14 -0
- package/script/helpers/stabilizeCosineVectors.d.ts.map +1 -0
- package/script/helpers/stabilizeCosineVectors.js +40 -0
- package/script/helpers/stringToArray.d.ts +4 -3
- package/script/helpers/stringToArray.d.ts.map +1 -1
- package/script/helpers/stringToArray.js +4 -3
- package/script/helpers/updateColumnsWithJS.d.ts +12 -6
- package/script/helpers/updateColumnsWithJS.d.ts.map +1 -1
- package/script/helpers/updateColumnsWithJS.js +12 -6
- package/script/helpers/validateGraphRouteResultSchema.d.ts +4 -0
- package/script/helpers/validateGraphRouteResultSchema.d.ts.map +1 -0
- package/script/helpers/validateGraphRouteResultSchema.js +19 -0
- package/script/helpers/validateGraphTemporalEvents.d.ts +7 -0
- package/script/helpers/validateGraphTemporalEvents.d.ts.map +1 -0
- package/script/helpers/validateGraphTemporalEvents.js +53 -0
- package/script/helpers/validateNumericalAnalysis.d.ts +10 -6
- package/script/helpers/validateNumericalAnalysis.d.ts.map +1 -1
- package/script/helpers/validateNumericalAnalysis.js +10 -6
- package/script/helpers/validateVectorRowIds.d.ts +4 -0
- package/script/helpers/validateVectorRowIds.d.ts.map +1 -0
- package/script/helpers/validateVectorRowIds.js +19 -0
- package/script/helpers/vectorDistanceExpression.d.ts +6 -0
- package/script/helpers/vectorDistanceExpression.d.ts.map +1 -0
- package/script/helpers/vectorDistanceExpression.js +14 -0
- package/script/helpers/wrapString.d.ts +10 -7
- package/script/helpers/wrapString.d.ts.map +1 -1
- package/script/helpers/wrapString.js +10 -7
- package/script/methods/addId.d.ts +5 -0
- package/script/methods/addId.d.ts.map +1 -0
- package/script/methods/addId.js +44 -0
- package/script/methods/commonNeighbors.d.ts +10 -0
- package/script/methods/commonNeighbors.d.ts.map +1 -0
- package/script/methods/commonNeighbors.js +140 -0
- package/script/methods/connectedComponents.d.ts +9 -0
- package/script/methods/connectedComponents.d.ts.map +1 -0
- package/script/methods/connectedComponents.js +186 -0
- package/script/methods/degree.d.ts +9 -0
- package/script/methods/degree.d.ts.map +1 -0
- package/script/methods/degree.js +141 -0
- package/script/methods/distances.d.ts +12 -0
- package/script/methods/distances.d.ts.map +1 -0
- package/script/methods/distances.js +203 -0
- package/script/methods/findCycles.d.ts +12 -0
- package/script/methods/findCycles.d.ts.map +1 -0
- package/script/methods/findCycles.js +369 -0
- package/script/methods/fuzzyClean.d.ts.map +1 -1
- package/script/methods/fuzzyClean.js +17 -136
- package/script/methods/fuzzyJoin.js +70 -16
- package/script/methods/getTypes.d.ts +1 -1
- package/script/methods/hdbscan.d.ts +5 -0
- package/script/methods/hdbscan.d.ts.map +1 -0
- package/script/methods/hdbscan.js +214 -0
- package/script/methods/mahalanobis.d.ts +5 -0
- package/script/methods/mahalanobis.d.ts.map +1 -0
- package/script/methods/mahalanobis.js +98 -0
- package/script/methods/neighbors.d.ts +9 -0
- package/script/methods/neighbors.d.ts.map +1 -0
- package/script/methods/neighbors.js +120 -0
- package/script/methods/normalizeVector.d.ts +5 -0
- package/script/methods/normalizeVector.d.ts.map +1 -0
- package/script/methods/normalizeVector.js +138 -0
- package/script/methods/paths.d.ts +12 -0
- package/script/methods/paths.d.ts.map +1 -0
- package/script/methods/paths.js +326 -0
- package/script/methods/reachable.d.ts +11 -0
- package/script/methods/reachable.d.ts.map +1 -0
- package/script/methods/reachable.js +170 -0
- package/script/methods/rowToVector.d.ts +5 -0
- package/script/methods/rowToVector.d.ts.map +1 -0
- package/script/methods/rowToVector.js +83 -0
- package/script/methods/shortestPath.d.ts +12 -0
- package/script/methods/shortestPath.d.ts.map +1 -0
- package/script/methods/shortestPath.js +376 -0
- package/script/methods/topologicalSort.d.ts +7 -0
- package/script/methods/topologicalSort.d.ts.map +1 -0
- package/script/methods/topologicalSort.js +170 -0
- package/script/methods/trim.d.ts +1 -1
- package/script/methods/trim.d.ts.map +1 -1
- package/script/methods/trim.js +17 -8
package/llm.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# The Simple Data Analysis (Core) Library
|
|
2
2
|
|
|
3
3
|
- Package: `@nshiab/simple-data-analysis-core`
|
|
4
|
-
- Version: `2.
|
|
4
|
+
- Version: `2.1.1`
|
|
5
5
|
|
|
6
6
|
To install the library with Deno, use:
|
|
7
7
|
|
|
@@ -1530,6 +1530,80 @@ await table.umap("embedding", {
|
|
|
1530
1530
|
}).selectColumns(["label", "umapX", "umapY"]).log();
|
|
1531
1531
|
```
|
|
1532
1532
|
|
|
1533
|
+
#### `hdbscan`
|
|
1534
|
+
|
|
1535
|
+
Groups rows with similar numeric features using HDBSCAN, without requiring a
|
|
1536
|
+
predefined number of clusters. Adds a VARCHAR column containing `"cluster-0"`,
|
|
1537
|
+
`"cluster-1"`, etc., or `"noise"` for rows outside clusters. Labels identify
|
|
1538
|
+
groups, not their rank.
|
|
1539
|
+
|
|
1540
|
+
Accepts a numeric vector column or several numeric scalar columns. Features are
|
|
1541
|
+
used as supplied. If their scales differ, consider preparing them with
|
|
1542
|
+
`normalize()`, `zScore()`, or `normalizeVector()` before clustering.
|
|
1543
|
+
|
|
1544
|
+
Exact clustering is the default and can be expensive for large datasets. Set
|
|
1545
|
+
`approximate: true` to use approximate clustering, which can produce different
|
|
1546
|
+
results, including between repeated runs.
|
|
1547
|
+
|
|
1548
|
+
##### Signature
|
|
1549
|
+
|
|
1550
|
+
```typescript
|
|
1551
|
+
hdbscan(columns: string | string[], newColumn: string, options?: { minClusterSize?: number; minSamples?: number; metric?: "euclidean" | "cosine"; allowSingleCluster?: boolean; approximate?: boolean; membershipScoreColumn?: string; outlierScoreColumn?: string }): this;
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
##### Parameters
|
|
1555
|
+
|
|
1556
|
+
- **`columns`**: A numeric vector column, or numeric scalar columns in
|
|
1557
|
+
feature-dimension order.
|
|
1558
|
+
- **`newColumn`**: The cluster-label column to create.
|
|
1559
|
+
- **`options`**: HDBSCAN clustering and output settings.
|
|
1560
|
+
- **`options.minClusterSize`**: Minimum cluster size, from `2` through the row
|
|
1561
|
+
count. Defaults to `5`.
|
|
1562
|
+
- **`options.minSamples`**: Number of neighbors used to estimate local density,
|
|
1563
|
+
excluding the point itself. Higher values make clustering more conservative,
|
|
1564
|
+
generally labeling more rows as noise. Set this separately to adjust density
|
|
1565
|
+
sensitivity independently of minimum cluster size. Defaults to
|
|
1566
|
+
`minClusterSize`.
|
|
1567
|
+
- **`options.metric`**: Use `"euclidean"` to compare feature values, or
|
|
1568
|
+
`"cosine"` to compare vector direction regardless of overall magnitude.
|
|
1569
|
+
Defaults to `"euclidean"`.
|
|
1570
|
+
- **`options.allowSingleCluster`**: Allow a result with just one cluster,
|
|
1571
|
+
possibly alongside noise. Defaults to `false`. Setting this to `true` can
|
|
1572
|
+
favor one broad group, even when there is little meaningful structure.
|
|
1573
|
+
- **`options.approximate`**: Use approximate clustering. Defaults to `false`.
|
|
1574
|
+
- **`options.membershipScoreColumn`**: Optional DOUBLE column for membership
|
|
1575
|
+
strength from `0` to `1`. Higher values indicate stronger membership in the
|
|
1576
|
+
assigned cluster; noise scores `0`.
|
|
1577
|
+
- **`options.outlierScoreColumn`**: Optional DOUBLE column for outlier scores
|
|
1578
|
+
from `0` to `1`. Higher values indicate more unusual rows relative to their
|
|
1579
|
+
surroundings, including within clusters. This is not necessarily
|
|
1580
|
+
`1 - membershipScore`.
|
|
1581
|
+
|
|
1582
|
+
##### Returns
|
|
1583
|
+
|
|
1584
|
+
The table, so methods can be chained.
|
|
1585
|
+
|
|
1586
|
+
##### Examples
|
|
1587
|
+
|
|
1588
|
+
```ts
|
|
1589
|
+
// Cluster numeric columns and add membership and outlier scores.
|
|
1590
|
+
await table
|
|
1591
|
+
.hdbscan(["height", "weight"], "cluster", {
|
|
1592
|
+
minClusterSize: 5,
|
|
1593
|
+
membershipScoreColumn: "membership",
|
|
1594
|
+
outlierScoreColumn: "outlierScore",
|
|
1595
|
+
})
|
|
1596
|
+
.log();
|
|
1597
|
+
```
|
|
1598
|
+
|
|
1599
|
+
```ts
|
|
1600
|
+
// Scale vector dimensions before clustering.
|
|
1601
|
+
await table
|
|
1602
|
+
.normalizeVector("features", "scaledFeatures")
|
|
1603
|
+
.hdbscan("scaledFeatures", "cluster")
|
|
1604
|
+
.log();
|
|
1605
|
+
```
|
|
1606
|
+
|
|
1533
1607
|
#### `bm25`
|
|
1534
1608
|
|
|
1535
1609
|
Searches a text column using DuckDB's BM25 ranking function, which scores
|
|
@@ -2336,17 +2410,20 @@ await table.removeMissing({ columns: "age", missingValues: [-1] }).log();
|
|
|
2336
2410
|
#### `trim`
|
|
2337
2411
|
|
|
2338
2412
|
Trims specified characters from the beginning, end, or both sides of string
|
|
2339
|
-
values in the given columns.
|
|
2413
|
+
values in the given columns. Pass `"all"` to trim every string (VARCHAR) column,
|
|
2414
|
+
leaving other types unchanged. If there are no string columns, `"all"` leaves
|
|
2415
|
+
the table unchanged. Use `["all"]` to trim a column literally named `all`.
|
|
2340
2416
|
|
|
2341
2417
|
##### Signature
|
|
2342
2418
|
|
|
2343
2419
|
```typescript
|
|
2344
|
-
trim(columns: string | string[], options?: { character?: string; side?: "left" | "right" | "both" }): this;
|
|
2420
|
+
trim(columns: "all" | string | string[], options?: { character?: string; side?: "left" | "right" | "both" }): this;
|
|
2345
2421
|
```
|
|
2346
2422
|
|
|
2347
2423
|
##### Parameters
|
|
2348
2424
|
|
|
2349
|
-
- **`columns`**: The column name
|
|
2425
|
+
- **`columns`**: The column name, an array of column names, or `"all"` to trim
|
|
2426
|
+
every string (VARCHAR) column.
|
|
2350
2427
|
- **`options`**: An optional object with configuration options:
|
|
2351
2428
|
- **`options.character`**: The string to trim. Defaults to whitespace
|
|
2352
2429
|
characters.
|
|
@@ -2365,6 +2442,11 @@ The table, so methods can be chained.
|
|
|
2365
2442
|
await table.trim("column1").log();
|
|
2366
2443
|
```
|
|
2367
2444
|
|
|
2445
|
+
```ts
|
|
2446
|
+
// Trim whitespace from every string column
|
|
2447
|
+
await table.trim("all").log();
|
|
2448
|
+
```
|
|
2449
|
+
|
|
2368
2450
|
```ts
|
|
2369
2451
|
// Trim leading and trailing asterisks from 'productCode'
|
|
2370
2452
|
await table.trim("productCode", { character: "*" }).log();
|
|
@@ -2928,31 +3010,28 @@ await table.loadArray([{ count: 3 }])
|
|
|
2928
3010
|
.log();
|
|
2929
3011
|
```
|
|
2930
3012
|
|
|
2931
|
-
#### `
|
|
3013
|
+
#### `addId`
|
|
2932
3014
|
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
3015
|
+
Adds a unique, non-null ID for each row in the current table. IDs start at `0`
|
|
3016
|
+
and identify rows within this table, including rows with identical contents.
|
|
3017
|
+
Without a prefix, the new column contains numbers. When a prefix is supplied,
|
|
3018
|
+
the new column contains strings with the exact prefix followed by the row
|
|
3019
|
+
number. An empty prefix therefore creates the strings `"0"`, `"1"`, and so on.
|
|
2936
3020
|
|
|
2937
|
-
|
|
2938
|
-
numbering, and `dayOfYear` starts at `1`. DuckDB `DATE`, `TIME`, `TIMESTAMP`,
|
|
2939
|
-
and `TIMESTAMP WITH TIME ZONE` columns are supported when the requested
|
|
2940
|
-
component applies to that type: date parts apply to dates and timestamps, while
|
|
2941
|
-
time parts apply to times and timestamps. `NULL` input values produce `NULL`
|
|
2942
|
-
extracted values. Parts extracted from `TIMESTAMP WITH TIME ZONE` values use
|
|
2943
|
-
UTC.
|
|
3021
|
+
IDs are not globally unique: separate tables can generate the same IDs.
|
|
2944
3022
|
|
|
2945
3023
|
##### Signature
|
|
2946
3024
|
|
|
2947
3025
|
```typescript
|
|
2948
|
-
|
|
3026
|
+
addId(newColumn: string, options?: { prefix?: string }): this;
|
|
2949
3027
|
```
|
|
2950
3028
|
|
|
2951
3029
|
##### Parameters
|
|
2952
3030
|
|
|
2953
|
-
- **`
|
|
2954
|
-
- **`
|
|
2955
|
-
|
|
3031
|
+
- **`newColumn`**: The name of the new ID column.
|
|
3032
|
+
- **`options`**: An optional object with configuration options.
|
|
3033
|
+
- **`options.prefix`**: Text to place before each row number. Supplying this
|
|
3034
|
+
option, including an empty string, creates string IDs.
|
|
2956
3035
|
|
|
2957
3036
|
##### Returns
|
|
2958
3037
|
|
|
@@ -2961,260 +3040,2006 @@ The table, so methods can be chained.
|
|
|
2961
3040
|
##### Examples
|
|
2962
3041
|
|
|
2963
3042
|
```ts
|
|
2964
|
-
// Add
|
|
2965
|
-
await table
|
|
3043
|
+
// Add numeric IDs: 0, 1, 2, ...
|
|
3044
|
+
await table
|
|
3045
|
+
.addId("edgeId")
|
|
3046
|
+
.log();
|
|
2966
3047
|
```
|
|
2967
3048
|
|
|
2968
3049
|
```ts
|
|
2969
|
-
//
|
|
2970
|
-
await
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
}).log();
|
|
3050
|
+
// Add string IDs: "flight-0", "flight-1", "flight-2", ...
|
|
3051
|
+
await flights
|
|
3052
|
+
.addId("edgeId", { prefix: "flight-" })
|
|
3053
|
+
.log();
|
|
2974
3054
|
```
|
|
2975
3055
|
|
|
2976
|
-
#### `
|
|
3056
|
+
#### `neighbors`
|
|
2977
3057
|
|
|
2978
|
-
|
|
2979
|
-
|
|
3058
|
+
Finds the distinct nodes directly connected to one or more starting nodes. The
|
|
3059
|
+
`direction` option lets you find neighbors from source to target, from target to
|
|
3060
|
+
source, or in either direction. The result has `start` and `node` columns,
|
|
3061
|
+
sorted in ascending order by `start`, then `node`.
|
|
3062
|
+
|
|
3063
|
+
Unknown starting IDs and starts with no neighbors in the selected direction
|
|
3064
|
+
produce no rows. A self-connection includes the starting node once. Empty start
|
|
3065
|
+
arrays and duplicate starting IDs throw an error.
|
|
3066
|
+
|
|
3067
|
+
The next three examples each start with this data:
|
|
3068
|
+
|
|
3069
|
+
| origin | destination |
|
|
3070
|
+
| ------ | ----------- |
|
|
3071
|
+
| A | B |
|
|
3072
|
+
| A | B |
|
|
3073
|
+
| C | A |
|
|
3074
|
+
|
|
3075
|
+
By default, the method finds neighbors from source to target:
|
|
2980
3076
|
|
|
2981
3077
|
##### Signature
|
|
2982
3078
|
|
|
2983
3079
|
```typescript
|
|
2984
|
-
|
|
3080
|
+
neighbors(sourceColumn: string, targetColumn: string, startNodes: string | number | bigint | (string | number | bigint)[], options?: { direction?: "outgoing" | "incoming" | "both"; outputTable?: string | boolean }): SimpleTable;
|
|
2985
3081
|
```
|
|
2986
3082
|
|
|
2987
3083
|
##### Parameters
|
|
2988
3084
|
|
|
2989
|
-
- **`
|
|
2990
|
-
|
|
2991
|
-
- **`
|
|
2992
|
-
|
|
3085
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
3086
|
+
node ID.
|
|
3087
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
3088
|
+
node ID.
|
|
3089
|
+
- **`startNodes`**: One starting node ID or an array of distinct starting node
|
|
3090
|
+
IDs.
|
|
3091
|
+
- **`options`**: An optional object with direction and result configuration.
|
|
3092
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
3093
|
+
Defaults to `"outgoing"`.
|
|
3094
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3095
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3096
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
2993
3097
|
|
|
2994
3098
|
##### Returns
|
|
2995
3099
|
|
|
2996
|
-
The table, so methods can be chained.
|
|
3100
|
+
The result table, so methods can be chained.
|
|
2997
3101
|
|
|
2998
3102
|
##### Examples
|
|
2999
3103
|
|
|
3000
3104
|
```ts
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
```ts
|
|
3006
|
-
// Add a new column named 'rowNumber' with the row number for each 'category'
|
|
3007
|
-
await table.addRowNumber("rowNumber", { by: "category" }).log();
|
|
3105
|
+
await table
|
|
3106
|
+
.neighbors("origin", "destination", "A")
|
|
3107
|
+
.log();
|
|
3008
3108
|
```
|
|
3009
3109
|
|
|
3010
|
-
|
|
3110
|
+
| start | node |
|
|
3111
|
+
| ----- | ---- |
|
|
3112
|
+
| A | B |
|
|
3011
3113
|
|
|
3012
|
-
|
|
3013
|
-
Cartesian product of the rows from both tables, meaning all possible pairs of
|
|
3014
|
-
rows will be in the resulting table. This means that if the left table has `n`
|
|
3015
|
-
rows and the right table has `m` rows, the result will have `n * m` rows.
|
|
3114
|
+
B appears only once, even though the input has two connections from A to B.
|
|
3016
3115
|
|
|
3017
|
-
|
|
3116
|
+
With `direction: "incoming"`, the method finds neighbors from target to source.
|
|
3117
|
+
Here, C connects to A:
|
|
3018
3118
|
|
|
3019
|
-
```
|
|
3020
|
-
|
|
3119
|
+
```ts
|
|
3120
|
+
await table
|
|
3121
|
+
.neighbors("origin", "destination", "A", { direction: "incoming" })
|
|
3122
|
+
.log();
|
|
3021
3123
|
```
|
|
3022
3124
|
|
|
3023
|
-
|
|
3125
|
+
| start | node |
|
|
3126
|
+
| ----- | ---- |
|
|
3127
|
+
| A | C |
|
|
3024
3128
|
|
|
3025
|
-
|
|
3026
|
-
- **`options`**: An optional object with configuration options:
|
|
3027
|
-
- **`options.outputTable`**: If `true`, the results will be stored in a new
|
|
3028
|
-
table with a generated name. If a string, it will be used as the name for the
|
|
3029
|
-
new table. If `false` or omitted, the current table will be overwritten.
|
|
3030
|
-
Defaults to `false`.
|
|
3129
|
+
With `direction: "both"`, the method finds neighbors in either direction:
|
|
3031
3130
|
|
|
3032
|
-
|
|
3131
|
+
```ts
|
|
3132
|
+
await table
|
|
3133
|
+
.neighbors("origin", "destination", "A", { direction: "both" })
|
|
3134
|
+
.log();
|
|
3135
|
+
```
|
|
3033
3136
|
|
|
3034
|
-
|
|
3035
|
-
|
|
3137
|
+
| start | node |
|
|
3138
|
+
| ----- | ---- |
|
|
3139
|
+
| A | B |
|
|
3140
|
+
| A | C |
|
|
3036
3141
|
|
|
3037
|
-
|
|
3142
|
+
Multiple starts are evaluated independently. For this input:
|
|
3038
3143
|
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3144
|
+
| source | target | cost |
|
|
3145
|
+
| -------- | ------- | ---: |
|
|
3146
|
+
| Montreal | Ottawa | 2 |
|
|
3147
|
+
| Ottawa | Toronto | 3 |
|
|
3043
3148
|
|
|
3044
3149
|
```ts
|
|
3045
|
-
|
|
3046
|
-
|
|
3150
|
+
await table
|
|
3151
|
+
.neighbors("source", "target", ["Montreal", "Ottawa"])
|
|
3152
|
+
.log();
|
|
3047
3153
|
```
|
|
3048
3154
|
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3155
|
+
| start | node |
|
|
3156
|
+
| -------- | ------- |
|
|
3157
|
+
| Montreal | Ottawa |
|
|
3158
|
+
| Ottawa | Toronto |
|
|
3053
3159
|
|
|
3054
|
-
#### `
|
|
3160
|
+
#### `degree`
|
|
3055
3161
|
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3162
|
+
Counts the incoming and outgoing connections for every node found in the source
|
|
3163
|
+
and target columns. By default, each input row is counted separately, even when
|
|
3164
|
+
several rows connect the same two nodes. Set the `count` option to `"neighbors"`
|
|
3165
|
+
to count distinct neighboring nodes instead. Use the `weight` option to sum
|
|
3166
|
+
values from a numeric column instead of counting connections. The `weight`
|
|
3167
|
+
option cannot be combined with `count: "neighbors"`.
|
|
3168
|
+
|
|
3169
|
+
The result has `node`, `incoming`, `outgoing`, and `total` columns. The `total`
|
|
3170
|
+
is the sum of `incoming` and `outgoing`. Results are sorted by highest total
|
|
3171
|
+
first, then by node in ascending order when totals are equal. A self-connection
|
|
3172
|
+
contributes once to incoming and once to outgoing, so it contributes twice to
|
|
3173
|
+
the total. With `count: "neighbors"`, a neighbor connected in both directions
|
|
3174
|
+
also contributes once in each direction. Endpoint IDs must be non-null strings
|
|
3175
|
+
or whole numbers in compatible columns. Supplied weights must be non-null,
|
|
3176
|
+
finite, and non-negative.
|
|
3177
|
+
|
|
3178
|
+
The next three examples each start with these flights:
|
|
3179
|
+
|
|
3180
|
+
| origin | destination | passengers |
|
|
3181
|
+
| -------- | ----------- | ---------: |
|
|
3182
|
+
| Montreal | Toronto | 100 |
|
|
3183
|
+
| Montreal | Toronto | 200 |
|
|
3184
|
+
| Montreal | Vancouver | 50 |
|
|
3185
|
+
| Toronto | Montreal | 150 |
|
|
3186
|
+
|
|
3187
|
+
By default, the method counts connections and overwrites the input table:
|
|
3061
3188
|
|
|
3062
3189
|
##### Signature
|
|
3063
3190
|
|
|
3064
3191
|
```typescript
|
|
3065
|
-
|
|
3192
|
+
degree(sourceColumn: string, targetColumn: string, options?: { count?: "edges" | "neighbors"; weight?: string; outputTable?: string | boolean }): SimpleTable;
|
|
3066
3193
|
```
|
|
3067
3194
|
|
|
3068
3195
|
##### Parameters
|
|
3069
3196
|
|
|
3070
|
-
- **`
|
|
3071
|
-
|
|
3072
|
-
- **`
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
- **`options.
|
|
3076
|
-
|
|
3077
|
-
- **`options.
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3197
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
3198
|
+
node ID.
|
|
3199
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
3200
|
+
node ID.
|
|
3201
|
+
- **`options`**: An optional object with counting and result configuration.
|
|
3202
|
+
- **`options.count`**: Whether to count connection rows (`"edges"`) or distinct
|
|
3203
|
+
adjacent nodes (`"neighbors"`). Defaults to `"edges"`.
|
|
3204
|
+
- **`options.weight`**: The name of the numeric edge-weight column to sum. This
|
|
3205
|
+
requires edge counting.
|
|
3206
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3207
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3208
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
3081
3209
|
|
|
3082
3210
|
##### Returns
|
|
3083
3211
|
|
|
3084
|
-
|
|
3085
|
-
table), so methods can be chained.
|
|
3212
|
+
The result table, so methods can be chained.
|
|
3086
3213
|
|
|
3087
3214
|
##### Examples
|
|
3088
3215
|
|
|
3089
3216
|
```ts
|
|
3090
|
-
|
|
3091
|
-
|
|
3217
|
+
await flights
|
|
3218
|
+
.degree("origin", "destination")
|
|
3219
|
+
.log();
|
|
3092
3220
|
```
|
|
3093
3221
|
|
|
3222
|
+
| node | incoming | outgoing | total |
|
|
3223
|
+
| --------- | -------: | -------: | ----: |
|
|
3224
|
+
| Montreal | 1 | 3 | 4 |
|
|
3225
|
+
| Toronto | 2 | 1 | 3 |
|
|
3226
|
+
| Vancouver | 1 | 0 | 1 |
|
|
3227
|
+
|
|
3228
|
+
With `count: "neighbors"`, the two Montreal-to-Toronto flights count as one
|
|
3229
|
+
outgoing neighbor for Montreal:
|
|
3230
|
+
|
|
3094
3231
|
```ts
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
type: "inner",
|
|
3099
|
-
outputTable: "tableC",
|
|
3100
|
-
}).log();
|
|
3232
|
+
await flights
|
|
3233
|
+
.degree("origin", "destination", { count: "neighbors" })
|
|
3234
|
+
.log();
|
|
3101
3235
|
```
|
|
3102
3236
|
|
|
3237
|
+
| node | incoming | outgoing | total |
|
|
3238
|
+
| --------- | -------: | -------: | ----: |
|
|
3239
|
+
| Montreal | 1 | 2 | 3 |
|
|
3240
|
+
| Toronto | 1 | 1 | 2 |
|
|
3241
|
+
| Vancouver | 1 | 0 | 1 |
|
|
3242
|
+
|
|
3243
|
+
With `weight: "passengers"`, the method adds passenger counts for each city's
|
|
3244
|
+
incoming and outgoing flights:
|
|
3245
|
+
|
|
3103
3246
|
```ts
|
|
3104
|
-
|
|
3105
|
-
|
|
3247
|
+
await flights
|
|
3248
|
+
.degree("origin", "destination", { weight: "passengers" })
|
|
3249
|
+
.log();
|
|
3106
3250
|
```
|
|
3107
3251
|
|
|
3108
|
-
|
|
3252
|
+
| node | incoming | outgoing | total |
|
|
3253
|
+
| --------- | -------: | -------: | ----: |
|
|
3254
|
+
| Montreal | 150 | 350 | 500 |
|
|
3255
|
+
| Toronto | 300 | 150 | 450 |
|
|
3256
|
+
| Vancouver | 50 | 0 | 50 |
|
|
3109
3257
|
|
|
3110
|
-
|
|
3111
|
-
another table (the right table) based on string similarity between two text
|
|
3112
|
-
columns. Uses the [rapidfuzz](https://query.farm/duckdb_extension_rapidfuzz)
|
|
3113
|
-
DuckDB community extension.
|
|
3258
|
+
A self-connection is counted once in each direction. For this input:
|
|
3114
3259
|
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
|
|
3260
|
+
| source | target |
|
|
3261
|
+
| ------ | ------ |
|
|
3262
|
+
| A | A |
|
|
3263
|
+
| A | B |
|
|
3119
3264
|
|
|
3120
|
-
|
|
3121
|
-
|
|
3265
|
+
```ts
|
|
3266
|
+
await connections
|
|
3267
|
+
.degree("source", "target")
|
|
3268
|
+
.log();
|
|
3269
|
+
```
|
|
3270
|
+
|
|
3271
|
+
| node | incoming | outgoing | total |
|
|
3272
|
+
| ---- | -------: | -------: | ----: |
|
|
3273
|
+
| A | 1 | 2 | 3 |
|
|
3274
|
+
| B | 1 | 0 | 1 |
|
|
3275
|
+
|
|
3276
|
+
#### `commonNeighbors`
|
|
3277
|
+
|
|
3278
|
+
Finds the neighbors shared by two different nodes. The `direction` option lets
|
|
3279
|
+
you find neighbors from source to target, from target to source, or in either
|
|
3280
|
+
direction. The result has one `node` column, sorted in ascending order.
|
|
3281
|
+
|
|
3282
|
+
If either node ID is unknown, or the nodes have no shared neighbors, the result
|
|
3283
|
+
has no rows. Each shared neighbor appears once, even if connections are
|
|
3284
|
+
repeated. A self-connection can make one of the requested nodes a shared
|
|
3285
|
+
neighbor. Using the same ID for both requested nodes throws an error.
|
|
3286
|
+
|
|
3287
|
+
The next three examples each start with this data:
|
|
3288
|
+
|
|
3289
|
+
| origin | destination |
|
|
3290
|
+
| ------ | ----------- |
|
|
3291
|
+
| A | C |
|
|
3292
|
+
| A | C |
|
|
3293
|
+
| B | C |
|
|
3294
|
+
| B | C |
|
|
3295
|
+
| D | A |
|
|
3296
|
+
| D | B |
|
|
3297
|
+
|
|
3298
|
+
By default, the method finds shared neighbors from source to target. Both A and
|
|
3299
|
+
B connect to C:
|
|
3122
3300
|
|
|
3123
3301
|
##### Signature
|
|
3124
3302
|
|
|
3125
3303
|
```typescript
|
|
3126
|
-
|
|
3304
|
+
commonNeighbors(sourceColumn: string, targetColumn: string, nodeA: string | number | bigint, nodeB: string | number | bigint, options?: { direction?: "outgoing" | "incoming" | "both"; outputTable?: string | boolean }): SimpleTable;
|
|
3127
3305
|
```
|
|
3128
3306
|
|
|
3129
3307
|
##### Parameters
|
|
3130
3308
|
|
|
3131
|
-
- **`
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
- **`
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
- **`options.
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
Similarity after sorting tokens (words), useful for reordered words. -
|
|
3144
|
-
`"token_set_ratio"`: Similarity based on sets of tokens, ignoring duplicates
|
|
3145
|
-
and word order.
|
|
3146
|
-
- **`options.similarityColumn`**: If provided, a column with this name is added
|
|
3147
|
-
to the result containing the similarity score (0–100). If omitted, the score
|
|
3148
|
-
is not included in the output.
|
|
3149
|
-
- **`options.outputTable`**: If `true`, the results will be stored in a new
|
|
3150
|
-
table with a generated name. If a string, it will be used as the name for the
|
|
3151
|
-
new table. If `false` or omitted, the current table will be overwritten.
|
|
3152
|
-
Defaults to `false`.
|
|
3153
|
-
- **`options.prefilterPrefixLength`**: An optional prefix length. Only strings
|
|
3154
|
-
sharing the same first N characters are compared. Note that prefix filtering
|
|
3155
|
-
is lossy (e.g. "John" vs. "Phon" will not match despite high similarity).
|
|
3309
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
3310
|
+
node ID.
|
|
3311
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
3312
|
+
node ID.
|
|
3313
|
+
- **`nodeA`**: The first node ID.
|
|
3314
|
+
- **`nodeB`**: The second node ID, which must differ from `nodeA`.
|
|
3315
|
+
- **`options`**: An optional object with direction and result configuration.
|
|
3316
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
3317
|
+
Defaults to `"outgoing"`.
|
|
3318
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3319
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3320
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
3156
3321
|
|
|
3157
3322
|
##### Returns
|
|
3158
3323
|
|
|
3159
|
-
|
|
3160
|
-
new table), so methods can be chained.
|
|
3324
|
+
The result table, so methods can be chained.
|
|
3161
3325
|
|
|
3162
3326
|
##### Examples
|
|
3163
3327
|
|
|
3164
3328
|
```ts
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3329
|
+
await connections
|
|
3330
|
+
.commonNeighbors("origin", "destination", "A", "B")
|
|
3331
|
+
.log();
|
|
3168
3332
|
```
|
|
3169
3333
|
|
|
3334
|
+
| node |
|
|
3335
|
+
| ---- |
|
|
3336
|
+
| C |
|
|
3337
|
+
|
|
3338
|
+
C appears only once, even though the input repeats the connections.
|
|
3339
|
+
|
|
3340
|
+
With `direction: "incoming"`, the method follows connections from target to
|
|
3341
|
+
source. D connects to both A and B:
|
|
3342
|
+
|
|
3170
3343
|
```ts
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
}).log();
|
|
3344
|
+
await connections
|
|
3345
|
+
.commonNeighbors("origin", "destination", "A", "B", { direction: "incoming" })
|
|
3346
|
+
.log();
|
|
3175
3347
|
```
|
|
3176
3348
|
|
|
3349
|
+
| node |
|
|
3350
|
+
| ---- |
|
|
3351
|
+
| D |
|
|
3352
|
+
|
|
3353
|
+
With `direction: "both"`, the method finds shared neighbors in either direction:
|
|
3354
|
+
|
|
3177
3355
|
```ts
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
outputTable: "tableC",
|
|
3182
|
-
}).log();
|
|
3356
|
+
await connections
|
|
3357
|
+
.commonNeighbors("origin", "destination", "A", "B", { direction: "both" })
|
|
3358
|
+
.log();
|
|
3183
3359
|
```
|
|
3184
3360
|
|
|
3361
|
+
| node |
|
|
3362
|
+
| ---- |
|
|
3363
|
+
| C |
|
|
3364
|
+
| D |
|
|
3365
|
+
|
|
3366
|
+
A self-connection can make a requested node a shared neighbor. For this input, A
|
|
3367
|
+
is a neighbor of both itself and B:
|
|
3368
|
+
|
|
3369
|
+
| source | target |
|
|
3370
|
+
| ------ | ------ |
|
|
3371
|
+
| A | A |
|
|
3372
|
+
| B | A |
|
|
3373
|
+
|
|
3185
3374
|
```ts
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
}).log();
|
|
3375
|
+
await connections
|
|
3376
|
+
.commonNeighbors("source", "target", "A", "B")
|
|
3377
|
+
.log();
|
|
3190
3378
|
```
|
|
3191
3379
|
|
|
3192
|
-
|
|
3380
|
+
| node |
|
|
3381
|
+
| ---- |
|
|
3382
|
+
| A |
|
|
3193
3383
|
|
|
3194
|
-
|
|
3195
|
-
them with a single canonical value.
|
|
3384
|
+
#### `reachable`
|
|
3196
3385
|
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
representative value based on the `strategy` option.
|
|
3386
|
+
Finds all nodes you can reach from one or more starting nodes, following one or
|
|
3387
|
+
more connections. The `direction` option lets you follow connections from source
|
|
3388
|
+
to target, from target to source, or in either direction. The result has `start`
|
|
3389
|
+
and `node` columns, sorted by `start`, then `node`.
|
|
3202
3390
|
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3391
|
+
A starting node appears in its own results only if following connections leads
|
|
3392
|
+
back to it, such as a self-connection or a cycle. Each reachable node appears
|
|
3393
|
+
only once per start. With `direction: "both"`, following the same connection out
|
|
3394
|
+
and back also reaches the starting node.
|
|
3395
|
+
|
|
3396
|
+
Unknown starting IDs and starts with no connections to follow produce no rows.
|
|
3397
|
+
Empty start arrays and duplicate starting IDs throw an error.
|
|
3398
|
+
|
|
3399
|
+
Use the `startTimeColumn` or `endTimeColumn` options to follow connections in
|
|
3400
|
+
chronological order. The `minGapMs` option sets the minimum gap between
|
|
3401
|
+
consecutive connections, in milliseconds. With both time columns, gaps are
|
|
3402
|
+
measured from one connection's end to the next connection's start; with one
|
|
3403
|
+
column, between their timestamps. The `strictOrdering` option defaults to
|
|
3404
|
+
`true`, rejecting zero-duration gaps. These options only work with
|
|
3405
|
+
`direction: "outgoing"` or `direction: "incoming"`.
|
|
3406
|
+
|
|
3407
|
+
The next four examples each start with this data:
|
|
3408
|
+
|
|
3409
|
+
| origin | destination |
|
|
3410
|
+
| ------ | ----------- |
|
|
3411
|
+
| A | B |
|
|
3412
|
+
| A | C |
|
|
3413
|
+
| B | D |
|
|
3414
|
+
| C | D |
|
|
3415
|
+
| D | A |
|
|
3416
|
+
|
|
3417
|
+
By default, the method follows connections from source to target. A appears in
|
|
3418
|
+
its own results because A → B → D → A leads back to it:
|
|
3206
3419
|
|
|
3207
3420
|
##### Signature
|
|
3208
3421
|
|
|
3209
3422
|
```typescript
|
|
3210
|
-
|
|
3423
|
+
reachable(sourceColumn: string, targetColumn: string, startNodes: string | number | bigint | (string | number | bigint)[], options?: { direction?: "outgoing" | "incoming" | "both"; endTimeColumn?: string; minGapMs?: number; outputTable?: string | boolean; startTimeColumn?: string; strictOrdering?: boolean }): SimpleTable;
|
|
3211
3424
|
```
|
|
3212
3425
|
|
|
3213
3426
|
##### Parameters
|
|
3214
3427
|
|
|
3215
|
-
- **`
|
|
3216
|
-
|
|
3217
|
-
|
|
3428
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
3429
|
+
node ID.
|
|
3430
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
3431
|
+
node ID.
|
|
3432
|
+
- **`startNodes`**: One starting node ID or an array of distinct starting node
|
|
3433
|
+
IDs.
|
|
3434
|
+
- **`options`**: An optional object with direction, time, and result
|
|
3435
|
+
configuration.
|
|
3436
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
3437
|
+
Defaults to `"outgoing"`.
|
|
3438
|
+
- **`options.startTimeColumn`**: The name of the column containing each
|
|
3439
|
+
connection's start time. Use this or `endTimeColumn` to follow connections in
|
|
3440
|
+
chronological order.
|
|
3441
|
+
- **`options.endTimeColumn`**: The name of the column containing each
|
|
3442
|
+
connection's end time. Use this or `startTimeColumn` to follow connections in
|
|
3443
|
+
chronological order.
|
|
3444
|
+
- **`options.minGapMs`**: The minimum gap between consecutive connections, in
|
|
3445
|
+
milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time
|
|
3446
|
+
column.
|
|
3447
|
+
- **`options.strictOrdering`**: Whether to reject zero-duration gaps between
|
|
3448
|
+
consecutive connections (equal timestamps). Defaults to `true`. Requires a
|
|
3449
|
+
time column.
|
|
3450
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3451
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3452
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
3453
|
+
|
|
3454
|
+
##### Returns
|
|
3455
|
+
|
|
3456
|
+
The result table, so methods can be chained.
|
|
3457
|
+
|
|
3458
|
+
##### Examples
|
|
3459
|
+
|
|
3460
|
+
```ts
|
|
3461
|
+
await connections
|
|
3462
|
+
.reachable("origin", "destination", "A")
|
|
3463
|
+
.log();
|
|
3464
|
+
```
|
|
3465
|
+
|
|
3466
|
+
| start | node |
|
|
3467
|
+
| ----- | ---- |
|
|
3468
|
+
| A | A |
|
|
3469
|
+
| A | B |
|
|
3470
|
+
| A | C |
|
|
3471
|
+
| A | D |
|
|
3472
|
+
|
|
3473
|
+
With `direction: "incoming"`, connections are followed from target to source.
|
|
3474
|
+
Starting at B:
|
|
3475
|
+
|
|
3476
|
+
```ts
|
|
3477
|
+
await connections
|
|
3478
|
+
.reachable("origin", "destination", "B", { direction: "incoming" })
|
|
3479
|
+
.log();
|
|
3480
|
+
```
|
|
3481
|
+
|
|
3482
|
+
| start | node |
|
|
3483
|
+
| ----- | ---- |
|
|
3484
|
+
| B | A |
|
|
3485
|
+
| B | B |
|
|
3486
|
+
| B | C |
|
|
3487
|
+
| B | D |
|
|
3488
|
+
|
|
3489
|
+
With `direction: "both"`, connections can be followed in either direction:
|
|
3490
|
+
|
|
3491
|
+
```ts
|
|
3492
|
+
await connections
|
|
3493
|
+
.reachable("origin", "destination", "B", { direction: "both" })
|
|
3494
|
+
.log();
|
|
3495
|
+
```
|
|
3496
|
+
|
|
3497
|
+
| start | node |
|
|
3498
|
+
| ----- | ---- |
|
|
3499
|
+
| B | A |
|
|
3500
|
+
| B | B |
|
|
3501
|
+
| B | C |
|
|
3502
|
+
| B | D |
|
|
3503
|
+
|
|
3504
|
+
With multiple starting nodes, each has its own results:
|
|
3505
|
+
|
|
3506
|
+
```ts
|
|
3507
|
+
await connections
|
|
3508
|
+
.reachable("origin", "destination", ["B", "A"])
|
|
3509
|
+
.log();
|
|
3510
|
+
```
|
|
3511
|
+
|
|
3512
|
+
| start | node |
|
|
3513
|
+
| ----- | ---- |
|
|
3514
|
+
| A | A |
|
|
3515
|
+
| A | B |
|
|
3516
|
+
| A | C |
|
|
3517
|
+
| A | D |
|
|
3518
|
+
| B | A |
|
|
3519
|
+
| B | B |
|
|
3520
|
+
| B | C |
|
|
3521
|
+
| B | D |
|
|
3522
|
+
|
|
3523
|
+
Chronological options retain only journeys with valid connection times. Here, A
|
|
3524
|
+
→ B arrives at 10:00, so the 09:00 connection to C is unavailable, while the
|
|
3525
|
+
11:00 connection to D meets the one-hour minimum gap:
|
|
3526
|
+
|
|
3527
|
+
| origin | destination | departureTime | arrivalTime |
|
|
3528
|
+
| ------ | ----------- | ---------------- | ---------------- |
|
|
3529
|
+
| A | B | 2025-01-01 08:00 | 2025-01-01 10:00 |
|
|
3530
|
+
| B | C | 2025-01-01 09:00 | 2025-01-01 10:00 |
|
|
3531
|
+
| B | D | 2025-01-01 11:00 | 2025-01-01 12:00 |
|
|
3532
|
+
|
|
3533
|
+
The departure and arrival columns are timestamps:
|
|
3534
|
+
|
|
3535
|
+
```ts
|
|
3536
|
+
await flights
|
|
3537
|
+
.reachable("origin", "destination", "A", {
|
|
3538
|
+
startTimeColumn: "departureTime",
|
|
3539
|
+
endTimeColumn: "arrivalTime",
|
|
3540
|
+
minGapMs: 60 * 60 * 1000,
|
|
3541
|
+
})
|
|
3542
|
+
.log();
|
|
3543
|
+
```
|
|
3544
|
+
|
|
3545
|
+
| start | node |
|
|
3546
|
+
| ----- | ---- |
|
|
3547
|
+
| A | B |
|
|
3548
|
+
| A | D |
|
|
3549
|
+
|
|
3550
|
+
#### `connectedComponents`
|
|
3551
|
+
|
|
3552
|
+
Groups nodes that are connected to one another, directly or through other nodes.
|
|
3553
|
+
By default, connection direction is ignored. With the `mode` option set to
|
|
3554
|
+
"strong", nodes belong to the same group only if each can reach all the others
|
|
3555
|
+
by following connections from source to target.
|
|
3556
|
+
|
|
3557
|
+
The result has `componentId` and `node` columns. Without `startTimeColumn` or
|
|
3558
|
+
`endTimeColumn`, each node appears once, and rows are sorted by node. Groups are
|
|
3559
|
+
numbered from zero in order of their smallest node ID.
|
|
3560
|
+
|
|
3561
|
+
Use the `startTimeColumn` or `endTimeColumn` options to follow connections in
|
|
3562
|
+
chronological order. The `minGapMs` option sets the minimum gap between
|
|
3563
|
+
consecutive connections, in milliseconds. With both time columns, gaps are
|
|
3564
|
+
measured from one connection's end to the next connection's start; with one
|
|
3565
|
+
column, between their timestamps. The `strictOrdering` option defaults to
|
|
3566
|
+
`true`, rejecting zero-duration gaps. These options require an explicitly
|
|
3567
|
+
supplied `mode: "strong"`.
|
|
3568
|
+
|
|
3569
|
+
With these options, nodes are grouped when each can reach all the others in
|
|
3570
|
+
chronological order. Groups can overlap, so a node may appear in several rows
|
|
3571
|
+
with different `componentId` values.
|
|
3572
|
+
|
|
3573
|
+
For the first example, we start with this data:
|
|
3574
|
+
|
|
3575
|
+
| origin | destination |
|
|
3576
|
+
| ------ | ----------- |
|
|
3577
|
+
| A | B |
|
|
3578
|
+
| C | D |
|
|
3579
|
+
|
|
3580
|
+
By default, the method groups connected nodes without considering direction. B
|
|
3581
|
+
and D are included even though they only appear as destinations:
|
|
3582
|
+
|
|
3583
|
+
##### Signature
|
|
3584
|
+
|
|
3585
|
+
```typescript
|
|
3586
|
+
connectedComponents(sourceColumn: string, targetColumn: string, options?: { endTimeColumn?: string; minGapMs?: number; mode?: "weak" | "strong"; outputTable?: string | boolean; startTimeColumn?: string; strictOrdering?: boolean }): SimpleTable;
|
|
3587
|
+
```
|
|
3588
|
+
|
|
3589
|
+
##### Parameters
|
|
3590
|
+
|
|
3591
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
3592
|
+
node ID.
|
|
3593
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
3594
|
+
node ID.
|
|
3595
|
+
- **`options`**: An optional object with component, time, and result
|
|
3596
|
+
configuration.
|
|
3597
|
+
- **`options.mode`**: Whether to find `"weak"` or `"strong"` components.
|
|
3598
|
+
Defaults to `"weak"`. Using `startTimeColumn` or `endTimeColumn` requires
|
|
3599
|
+
explicitly setting `mode: "strong"`.
|
|
3600
|
+
- **`options.startTimeColumn`**: The name of the column containing each
|
|
3601
|
+
connection's start time. Use this or `endTimeColumn` to follow connections in
|
|
3602
|
+
chronological order.
|
|
3603
|
+
- **`options.endTimeColumn`**: The name of the column containing each
|
|
3604
|
+
connection's end time. Use this or `startTimeColumn` to follow connections in
|
|
3605
|
+
chronological order.
|
|
3606
|
+
- **`options.minGapMs`**: The minimum gap between consecutive connections, in
|
|
3607
|
+
milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time
|
|
3608
|
+
column.
|
|
3609
|
+
- **`options.strictOrdering`**: Whether to reject zero-duration gaps between
|
|
3610
|
+
consecutive connections (equal timestamps). Defaults to `true`. Requires a
|
|
3611
|
+
time column.
|
|
3612
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3613
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3614
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
3615
|
+
|
|
3616
|
+
##### Returns
|
|
3617
|
+
|
|
3618
|
+
The result table, so methods can be chained.
|
|
3619
|
+
|
|
3620
|
+
##### Examples
|
|
3621
|
+
|
|
3622
|
+
```ts
|
|
3623
|
+
await table
|
|
3624
|
+
.connectedComponents("origin", "destination")
|
|
3625
|
+
.log();
|
|
3626
|
+
```
|
|
3627
|
+
|
|
3628
|
+
| componentId | node |
|
|
3629
|
+
| ----------: | ---- |
|
|
3630
|
+
| 0 | A |
|
|
3631
|
+
| 0 | B |
|
|
3632
|
+
| 1 | C |
|
|
3633
|
+
| 1 | D |
|
|
3634
|
+
|
|
3635
|
+
The next two examples each start with this chain of connections:
|
|
3636
|
+
|
|
3637
|
+
| source | target |
|
|
3638
|
+
| ------ | ------ |
|
|
3639
|
+
| A | B |
|
|
3640
|
+
| B | C |
|
|
3641
|
+
|
|
3642
|
+
By default, all three nodes belong to the same group:
|
|
3643
|
+
|
|
3644
|
+
```ts
|
|
3645
|
+
await graph
|
|
3646
|
+
.connectedComponents("source", "target")
|
|
3647
|
+
.log();
|
|
3648
|
+
```
|
|
3649
|
+
|
|
3650
|
+
| componentId | node |
|
|
3651
|
+
| ----------: | ---- |
|
|
3652
|
+
| 0 | A |
|
|
3653
|
+
| 0 | B |
|
|
3654
|
+
| 0 | C |
|
|
3655
|
+
|
|
3656
|
+
With the `mode` option set to "strong", each node forms its own group. A can
|
|
3657
|
+
reach B and C, but neither can get back to A:
|
|
3658
|
+
|
|
3659
|
+
```ts
|
|
3660
|
+
await graph
|
|
3661
|
+
.connectedComponents("source", "target", {
|
|
3662
|
+
mode: "strong",
|
|
3663
|
+
})
|
|
3664
|
+
.log();
|
|
3665
|
+
```
|
|
3666
|
+
|
|
3667
|
+
| componentId | node |
|
|
3668
|
+
| ----------: | ---- |
|
|
3669
|
+
| 0 | A |
|
|
3670
|
+
| 1 | B |
|
|
3671
|
+
| 2 | C |
|
|
3672
|
+
|
|
3673
|
+
Adding C -> A would let every node reach the others, so all three would belong
|
|
3674
|
+
to the same group in "strong" mode too.
|
|
3675
|
+
|
|
3676
|
+
Chronological strong groups can overlap. The next example uses one instantaneous
|
|
3677
|
+
timestamp column:
|
|
3678
|
+
|
|
3679
|
+
| time | source | target |
|
|
3680
|
+
| ---------------- | ------ | ------ |
|
|
3681
|
+
| 2025-01-01 08:00 | B | C |
|
|
3682
|
+
| 2025-01-01 09:00 | C | B |
|
|
3683
|
+
| 2025-01-01 10:00 | A | B |
|
|
3684
|
+
| 2025-01-01 11:00 | B | A |
|
|
3685
|
+
|
|
3686
|
+
A and B can reach each other, as can B and C, but A cannot reach C after its
|
|
3687
|
+
first event. This produces the maximal groups `{A, B}` and `{B, C}`:
|
|
3688
|
+
|
|
3689
|
+
```ts
|
|
3690
|
+
await transactions
|
|
3691
|
+
.connectedComponents("source", "target", {
|
|
3692
|
+
mode: "strong",
|
|
3693
|
+
startTimeColumn: "time",
|
|
3694
|
+
})
|
|
3695
|
+
.log();
|
|
3696
|
+
```
|
|
3697
|
+
|
|
3698
|
+
| componentId | node |
|
|
3699
|
+
| ----------: | ---- |
|
|
3700
|
+
| 0 | A |
|
|
3701
|
+
| 0 | B |
|
|
3702
|
+
| 1 | B |
|
|
3703
|
+
| 1 | C |
|
|
3704
|
+
|
|
3705
|
+
#### `topologicalSort`
|
|
3706
|
+
|
|
3707
|
+
Orders nodes so each prerequisite comes before the nodes that depend on it. Each
|
|
3708
|
+
input row means the source node must come before the target node. For example, A
|
|
3709
|
+
→ B means A must come before B.
|
|
3710
|
+
|
|
3711
|
+
The result has `node`, `componentId`, and `order` columns, sorted by
|
|
3712
|
+
`componentId`, then `order`. Nodes connected directly or through other nodes
|
|
3713
|
+
belong to the same group, ignoring connection direction. Groups are numbered
|
|
3714
|
+
from zero, with the group containing the smallest node ID first.
|
|
3715
|
+
|
|
3716
|
+
Within each group, `order` starts at one. When several nodes are ready, the
|
|
3717
|
+
method chooses the smallest node ID first: numeric order for numbers and
|
|
3718
|
+
character order for strings. All nodes in the source and target columns are
|
|
3719
|
+
included.
|
|
3720
|
+
|
|
3721
|
+
If dependencies form a loop, there is no valid order and the method throws an
|
|
3722
|
+
error. A node depending on itself also causes an error. An empty input produces
|
|
3723
|
+
no rows.
|
|
3724
|
+
|
|
3725
|
+
For this example, we start with these connections:
|
|
3726
|
+
|
|
3727
|
+
| source | target |
|
|
3728
|
+
| ------ | ------ |
|
|
3729
|
+
| A | B |
|
|
3730
|
+
| B | C |
|
|
3731
|
+
| D | C |
|
|
3732
|
+
|
|
3733
|
+
A must come before B, and both B and D must come before C:
|
|
3734
|
+
|
|
3735
|
+
##### Signature
|
|
3736
|
+
|
|
3737
|
+
```typescript
|
|
3738
|
+
topologicalSort(sourceColumn: string, targetColumn: string, options?: { outputTable?: string | boolean }): SimpleTable;
|
|
3739
|
+
```
|
|
3740
|
+
|
|
3741
|
+
##### Parameters
|
|
3742
|
+
|
|
3743
|
+
- **`sourceColumn`**: The name of the column containing each prerequisite node
|
|
3744
|
+
ID.
|
|
3745
|
+
- **`targetColumn`**: The name of the column containing each dependent node ID.
|
|
3746
|
+
- **`options`**: An optional object with result configuration.
|
|
3747
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3748
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3749
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
3750
|
+
|
|
3751
|
+
##### Returns
|
|
3752
|
+
|
|
3753
|
+
The result table, so methods can be chained.
|
|
3754
|
+
|
|
3755
|
+
##### Examples
|
|
3756
|
+
|
|
3757
|
+
```ts
|
|
3758
|
+
await table
|
|
3759
|
+
.topologicalSort("source", "target")
|
|
3760
|
+
.log();
|
|
3761
|
+
```
|
|
3762
|
+
|
|
3763
|
+
| node | componentId | order |
|
|
3764
|
+
| ---- | ----------: | ----: |
|
|
3765
|
+
| A | 0 | 1 |
|
|
3766
|
+
| B | 0 | 2 |
|
|
3767
|
+
| D | 0 | 3 |
|
|
3768
|
+
| C | 0 | 4 |
|
|
3769
|
+
|
|
3770
|
+
C comes last because it depends on both B and D. A comes before D because both
|
|
3771
|
+
are initially ready and A has the smaller ID. After A, B is ready and comes
|
|
3772
|
+
before D for the same reason.
|
|
3773
|
+
|
|
3774
|
+
With two independent groups, each has its own order starting at one. This
|
|
3775
|
+
example starts with different data:
|
|
3776
|
+
|
|
3777
|
+
| source | target |
|
|
3778
|
+
| ------ | ------ |
|
|
3779
|
+
| A | D |
|
|
3780
|
+
| B | C |
|
|
3781
|
+
|
|
3782
|
+
```ts
|
|
3783
|
+
await table
|
|
3784
|
+
.topologicalSort("source", "target")
|
|
3785
|
+
.log();
|
|
3786
|
+
```
|
|
3787
|
+
|
|
3788
|
+
| node | componentId | order |
|
|
3789
|
+
| ---- | ----------: | ----: |
|
|
3790
|
+
| A | 0 | 1 |
|
|
3791
|
+
| D | 0 | 2 |
|
|
3792
|
+
| B | 1 | 1 |
|
|
3793
|
+
| C | 1 | 2 |
|
|
3794
|
+
|
|
3795
|
+
#### `distances`
|
|
3796
|
+
|
|
3797
|
+
Finds the shortest distance from each starting node to every node it can reach
|
|
3798
|
+
by following one or more connections. By default, distance is the number of
|
|
3799
|
+
connections along the shortest route. Use the `weight` option to find the
|
|
3800
|
+
smallest sum of values from a numeric column, such as travel time.
|
|
3801
|
+
|
|
3802
|
+
The `direction` option lets you follow connections from source to target, from
|
|
3803
|
+
target to source, or in either direction. The result has `start`, `node`, and
|
|
3804
|
+
`distance` columns, sorted by `start`, then by increasing `distance`, then by
|
|
3805
|
+
`node` to break ties. The closest nodes appear first for each start.
|
|
3806
|
+
|
|
3807
|
+
Each row gives the shortest distance from `start` to `node`. Intermediate steps
|
|
3808
|
+
along the route are not returned. To get the steps between two different nodes,
|
|
3809
|
+
use `shortestPath()` for the shortest routes or `paths()` for all routes without
|
|
3810
|
+
repeated nodes.
|
|
3811
|
+
|
|
3812
|
+
A starting node appears in its own results only when a self-connection or a
|
|
3813
|
+
route leads back to it. Its distance is the shortest actual return route, using
|
|
3814
|
+
at least one connection. With `direction: "both"`, this can mean following the
|
|
3815
|
+
same connection out and back.
|
|
3816
|
+
|
|
3817
|
+
Unknown starting IDs and starts with no connections to follow produce no rows.
|
|
3818
|
+
Empty start arrays and duplicate starting IDs throw an error. Weights must be
|
|
3819
|
+
non-null, finite, and non-negative.
|
|
3820
|
+
|
|
3821
|
+
Use the `startTimeColumn` or `endTimeColumn` options to follow connections in
|
|
3822
|
+
chronological order. The `minGapMs` option sets the minimum gap between
|
|
3823
|
+
consecutive connections, in milliseconds. With both time columns, gaps are
|
|
3824
|
+
measured from one connection's end to the next connection's start; with one
|
|
3825
|
+
column, between their timestamps. The `strictOrdering` option defaults to
|
|
3826
|
+
`true`, rejecting zero-duration gaps. These options only work with
|
|
3827
|
+
`direction: "outgoing"` or `direction: "incoming"`.
|
|
3828
|
+
|
|
3829
|
+
The minimum gap applies only between consecutive connections, not before the
|
|
3830
|
+
first connection.
|
|
3831
|
+
|
|
3832
|
+
The next five examples each start with this data:
|
|
3833
|
+
|
|
3834
|
+
| origin | destination | minutes |
|
|
3835
|
+
| ------ | ----------- | ------: |
|
|
3836
|
+
| A | B | 4 |
|
|
3837
|
+
| B | C | 1 |
|
|
3838
|
+
| D | B | 2 |
|
|
3839
|
+
|
|
3840
|
+
By default, the method follows connections from source to target and counts how
|
|
3841
|
+
many connections are needed:
|
|
3842
|
+
|
|
3843
|
+
##### Signature
|
|
3844
|
+
|
|
3845
|
+
```typescript
|
|
3846
|
+
distances(sourceColumn: string, targetColumn: string, startNodes: string | number | bigint | (string | number | bigint)[], options?: { direction?: "outgoing" | "incoming" | "both"; endTimeColumn?: string; minGapMs?: number; outputTable?: string | boolean; startTimeColumn?: string; strictOrdering?: boolean; weight?: string }): SimpleTable;
|
|
3847
|
+
```
|
|
3848
|
+
|
|
3849
|
+
##### Parameters
|
|
3850
|
+
|
|
3851
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
3852
|
+
node ID.
|
|
3853
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
3854
|
+
node ID.
|
|
3855
|
+
- **`startNodes`**: One starting node ID or an array of distinct starting node
|
|
3856
|
+
IDs.
|
|
3857
|
+
- **`options`**: An optional object with direction, time, and result
|
|
3858
|
+
configuration.
|
|
3859
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
3860
|
+
Defaults to `"outgoing"`.
|
|
3861
|
+
- **`options.startTimeColumn`**: The name of the column containing each
|
|
3862
|
+
connection's start time. Use this or `endTimeColumn` to follow connections in
|
|
3863
|
+
chronological order.
|
|
3864
|
+
- **`options.endTimeColumn`**: The name of the column containing each
|
|
3865
|
+
connection's end time. Use this or `startTimeColumn` to follow connections in
|
|
3866
|
+
chronological order.
|
|
3867
|
+
- **`options.minGapMs`**: The minimum gap between consecutive connections, in
|
|
3868
|
+
milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time
|
|
3869
|
+
column.
|
|
3870
|
+
- **`options.strictOrdering`**: Whether to reject zero-duration gaps between
|
|
3871
|
+
consecutive connections (equal timestamps). Defaults to `true`. Requires a
|
|
3872
|
+
time column.
|
|
3873
|
+
- **`options.weight`**: The name of the numeric column used as the cost of each
|
|
3874
|
+
connection. If omitted, each connection costs one.
|
|
3875
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
3876
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
3877
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
3878
|
+
|
|
3879
|
+
##### Returns
|
|
3880
|
+
|
|
3881
|
+
The result table, so methods can be chained.
|
|
3882
|
+
|
|
3883
|
+
##### Examples
|
|
3884
|
+
|
|
3885
|
+
```ts
|
|
3886
|
+
await connections
|
|
3887
|
+
.distances("origin", "destination", "A")
|
|
3888
|
+
.log();
|
|
3889
|
+
```
|
|
3890
|
+
|
|
3891
|
+
| start | node | distance |
|
|
3892
|
+
| ----- | ---- | -------: |
|
|
3893
|
+
| A | B | 1 |
|
|
3894
|
+
| A | C | 2 |
|
|
3895
|
+
|
|
3896
|
+
With `weight: "minutes"`, distance is the shortest total travel time:
|
|
3897
|
+
|
|
3898
|
+
```ts
|
|
3899
|
+
await connections
|
|
3900
|
+
.distances("origin", "destination", "A", { weight: "minutes" })
|
|
3901
|
+
.log();
|
|
3902
|
+
```
|
|
3903
|
+
|
|
3904
|
+
| start | node | distance |
|
|
3905
|
+
| ----- | ---- | -------: |
|
|
3906
|
+
| A | B | 4 |
|
|
3907
|
+
| A | C | 5 |
|
|
3908
|
+
|
|
3909
|
+
With `direction: "incoming"`, connections are followed from target to source.
|
|
3910
|
+
Starting at C:
|
|
3911
|
+
|
|
3912
|
+
```ts
|
|
3913
|
+
await connections
|
|
3914
|
+
.distances("origin", "destination", "C", { direction: "incoming" })
|
|
3915
|
+
.log();
|
|
3916
|
+
```
|
|
3917
|
+
|
|
3918
|
+
| start | node | distance |
|
|
3919
|
+
| ----- | ---- | -------: |
|
|
3920
|
+
| C | B | 1 |
|
|
3921
|
+
| C | A | 2 |
|
|
3922
|
+
| C | D | 2 |
|
|
3923
|
+
|
|
3924
|
+
With `direction: "both"`, connections can be followed in either direction:
|
|
3925
|
+
|
|
3926
|
+
```ts
|
|
3927
|
+
await connections
|
|
3928
|
+
.distances("origin", "destination", "A", { direction: "both" })
|
|
3929
|
+
.log();
|
|
3930
|
+
```
|
|
3931
|
+
|
|
3932
|
+
| start | node | distance |
|
|
3933
|
+
| ----- | ---- | -------: |
|
|
3934
|
+
| A | B | 1 |
|
|
3935
|
+
| A | A | 2 |
|
|
3936
|
+
| A | C | 2 |
|
|
3937
|
+
| A | D | 2 |
|
|
3938
|
+
|
|
3939
|
+
A appears at distance 2 because A → B → A follows a connection out and back.
|
|
3940
|
+
|
|
3941
|
+
An array of starting nodes gives separate distances for each start:
|
|
3942
|
+
|
|
3943
|
+
```ts
|
|
3944
|
+
await connections
|
|
3945
|
+
.distances("origin", "destination", ["D", "A"], {
|
|
3946
|
+
weight: "minutes",
|
|
3947
|
+
})
|
|
3948
|
+
.log();
|
|
3949
|
+
```
|
|
3950
|
+
|
|
3951
|
+
| start | node | distance |
|
|
3952
|
+
| ----- | ---- | -------: |
|
|
3953
|
+
| A | B | 4 |
|
|
3954
|
+
| A | C | 5 |
|
|
3955
|
+
| D | B | 2 |
|
|
3956
|
+
| D | C | 3 |
|
|
3957
|
+
|
|
3958
|
+
A direct self-connection and a longer return route can both lead back to the
|
|
3959
|
+
start. This example uses different data:
|
|
3960
|
+
|
|
3961
|
+
| origin | destination | minutes |
|
|
3962
|
+
| ------ | ----------- | ------: |
|
|
3963
|
+
| A | A | 10 |
|
|
3964
|
+
| A | B | 2 |
|
|
3965
|
+
| B | A | 3 |
|
|
3966
|
+
|
|
3967
|
+
The shortest return to A takes 5 minutes through B, compared with 10 minutes for
|
|
3968
|
+
the direct self-connection:
|
|
3969
|
+
|
|
3970
|
+
```ts
|
|
3971
|
+
await connections
|
|
3972
|
+
.distances("origin", "destination", "A", { weight: "minutes" })
|
|
3973
|
+
.log();
|
|
3974
|
+
```
|
|
3975
|
+
|
|
3976
|
+
| start | node | distance |
|
|
3977
|
+
| ----- | ---- | -------: |
|
|
3978
|
+
| A | B | 2 |
|
|
3979
|
+
| A | A | 5 |
|
|
3980
|
+
|
|
3981
|
+
Chronological options can rule out a cheaper sequence that departs too early.
|
|
3982
|
+
For this example, F2 leaves before F1 arrives, while F3 meets the one-hour
|
|
3983
|
+
minimum exactly:
|
|
3984
|
+
|
|
3985
|
+
| origin | destination | departureTime | arrivalTime | minutes |
|
|
3986
|
+
| ------ | ----------- | ---------------- | ---------------- | ------: |
|
|
3987
|
+
| A | B | 2025-01-01 08:00 | 2025-01-01 10:00 | 2 |
|
|
3988
|
+
| B | C | 2025-01-01 09:00 | 2025-01-01 10:00 | 1 |
|
|
3989
|
+
| B | D | 2025-01-01 11:00 | 2025-01-01 12:00 | 3 |
|
|
3990
|
+
|
|
3991
|
+
```ts
|
|
3992
|
+
await scheduledFlights
|
|
3993
|
+
.distances("origin", "destination", "A", {
|
|
3994
|
+
startTimeColumn: "departureTime",
|
|
3995
|
+
endTimeColumn: "arrivalTime",
|
|
3996
|
+
minGapMs: 60 * 60 * 1000,
|
|
3997
|
+
weight: "minutes",
|
|
3998
|
+
})
|
|
3999
|
+
.log();
|
|
4000
|
+
```
|
|
4001
|
+
|
|
4002
|
+
| start | node | distance |
|
|
4003
|
+
| ----- | ---- | -------: |
|
|
4004
|
+
| A | B | 2 |
|
|
4005
|
+
| A | D | 5 |
|
|
4006
|
+
|
|
4007
|
+
#### `shortestPath`
|
|
4008
|
+
|
|
4009
|
+
Finds the shortest route between two different nodes. If several routes tie for
|
|
4010
|
+
shortest, all of them are returned. By default, the shortest route uses the
|
|
4011
|
+
fewest connections. Use the `weight` option to find the route with the smallest
|
|
4012
|
+
sum of values from a numeric column, such as travel time. A route cannot visit
|
|
4013
|
+
the same node twice, to avoid loops. Different routes can still share the same
|
|
4014
|
+
nodes.
|
|
4015
|
+
|
|
4016
|
+
The `direction` option lets you follow connections from source to target, from
|
|
4017
|
+
target to source, or in either direction.
|
|
4018
|
+
|
|
4019
|
+
Each connection needs a unique, non-null ID. Pass the name of the column
|
|
4020
|
+
containing these IDs as the `edgeId` argument. If your table is missing an ID
|
|
4021
|
+
column, you can easily create one with `addId()`.
|
|
4022
|
+
|
|
4023
|
+
The result starts with the `pathId`, `step`, `weight`, and `total` columns,
|
|
4024
|
+
followed by all original columns. Steps start at one and follow the search
|
|
4025
|
+
direction. The `weight` column is the connection cost, and `total` is the sum of
|
|
4026
|
+
those costs up to and including the current step. Without the `weight` option,
|
|
4027
|
+
each connection costs one.
|
|
4028
|
+
|
|
4029
|
+
If an input column is already named `pathId`, `step`, `weight`, or `total`
|
|
4030
|
+
(regardless of capitalization), the method throws an error. Rename it with
|
|
4031
|
+
`renameColumns()` first.
|
|
4032
|
+
|
|
4033
|
+
Each row is one connection along a route.
|
|
4034
|
+
|
|
4035
|
+
Use the `startTimeColumn` or `endTimeColumn` options to follow connections in
|
|
4036
|
+
chronological order. The `minGapMs` option sets the minimum gap between
|
|
4037
|
+
consecutive connections, in milliseconds. With both time columns, gaps are
|
|
4038
|
+
measured from one connection's end to the next connection's start; with one
|
|
4039
|
+
column, between their timestamps. The `strictOrdering` option defaults to
|
|
4040
|
+
`true`, rejecting zero-duration gaps. These options only work with
|
|
4041
|
+
`direction: "outgoing"` or `direction: "incoming"`.
|
|
4042
|
+
|
|
4043
|
+
The minimum gap applies only between consecutive connections, not before the
|
|
4044
|
+
first connection.
|
|
4045
|
+
|
|
4046
|
+
Routes are numbered from zero by comparing their sequences of connection IDs,
|
|
4047
|
+
element by element. Rows are sorted by `pathId`, then `step`.
|
|
4048
|
+
|
|
4049
|
+
Unknown IDs or nodes with no route between them produce no rows. The start and
|
|
4050
|
+
end must differ. Self-connections are ignored. Weights must be non-null, finite,
|
|
4051
|
+
and non-negative.
|
|
4052
|
+
|
|
4053
|
+
There is no limit on route length or the number of tied routes returned. Finding
|
|
4054
|
+
many tied routes can take a long time and use substantial memory.
|
|
4055
|
+
|
|
4056
|
+
The first example uses this table:
|
|
4057
|
+
|
|
4058
|
+
| edgeId | source | target |
|
|
4059
|
+
| ------ | ------ | ------ |
|
|
4060
|
+
| E1 | A | B |
|
|
4061
|
+
| E2 | A | C |
|
|
4062
|
+
| E3 | B | D |
|
|
4063
|
+
| E4 | C | D |
|
|
4064
|
+
| E5 | D | E |
|
|
4065
|
+
|
|
4066
|
+
By default, the method finds routes from source to target with the fewest
|
|
4067
|
+
connections. Two routes from A to E tie at three connections each:
|
|
4068
|
+
|
|
4069
|
+
##### Signature
|
|
4070
|
+
|
|
4071
|
+
```typescript
|
|
4072
|
+
shortestPath(sourceColumn: string, targetColumn: string, edgeId: string, start: string | number | bigint, end: string | number | bigint, options?: { direction?: "outgoing" | "incoming" | "both"; endTimeColumn?: string; minGapMs?: number; outputTable?: string | boolean; startTimeColumn?: string; strictOrdering?: boolean; weight?: string }): SimpleTable;
|
|
4073
|
+
```
|
|
4074
|
+
|
|
4075
|
+
##### Parameters
|
|
4076
|
+
|
|
4077
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
4078
|
+
node ID.
|
|
4079
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
4080
|
+
node ID.
|
|
4081
|
+
- **`edgeId`**: The name of the column uniquely identifying each connection
|
|
4082
|
+
(edge).
|
|
4083
|
+
- **`start`**: The starting node ID.
|
|
4084
|
+
- **`end`**: The ending node ID, which must differ from `start`.
|
|
4085
|
+
- **`options`**: An optional object with direction, time, and result
|
|
4086
|
+
configuration.
|
|
4087
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
4088
|
+
Defaults to `"outgoing"`.
|
|
4089
|
+
- **`options.startTimeColumn`**: The name of the column containing each
|
|
4090
|
+
connection's start time. Use this or `endTimeColumn` to follow connections in
|
|
4091
|
+
chronological order.
|
|
4092
|
+
- **`options.endTimeColumn`**: The name of the column containing each
|
|
4093
|
+
connection's end time. Use this or `startTimeColumn` to follow connections in
|
|
4094
|
+
chronological order.
|
|
4095
|
+
- **`options.minGapMs`**: The minimum gap between consecutive connections, in
|
|
4096
|
+
milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time
|
|
4097
|
+
column.
|
|
4098
|
+
- **`options.strictOrdering`**: Whether to reject zero-duration gaps between
|
|
4099
|
+
consecutive connections (equal timestamps). Defaults to `true`. Requires a
|
|
4100
|
+
time column.
|
|
4101
|
+
- **`options.weight`**: The name of the numeric column used as the cost of each
|
|
4102
|
+
connection. If omitted, each connection costs one.
|
|
4103
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
4104
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
4105
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
4106
|
+
|
|
4107
|
+
##### Returns
|
|
4108
|
+
|
|
4109
|
+
The result table, so methods can be chained.
|
|
4110
|
+
|
|
4111
|
+
##### Examples
|
|
4112
|
+
|
|
4113
|
+
```ts
|
|
4114
|
+
await connections
|
|
4115
|
+
.shortestPath("source", "target", "edgeId", "A", "E")
|
|
4116
|
+
.log();
|
|
4117
|
+
```
|
|
4118
|
+
|
|
4119
|
+
| pathId | step | weight | total | edgeId | source | target |
|
|
4120
|
+
| -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4121
|
+
| 0 | 1 | 1 | 1 | E1 | A | B |
|
|
4122
|
+
| 0 | 2 | 1 | 2 | E3 | B | D |
|
|
4123
|
+
| 0 | 3 | 1 | 3 | E5 | D | E |
|
|
4124
|
+
| 1 | 1 | 1 | 1 | E2 | A | C |
|
|
4125
|
+
| 1 | 2 | 1 | 2 | E4 | C | D |
|
|
4126
|
+
| 1 | 3 | 1 | 3 | E5 | D | E |
|
|
4127
|
+
|
|
4128
|
+
For an input without connection IDs, use `addId()` first:
|
|
4129
|
+
|
|
4130
|
+
| source | target |
|
|
4131
|
+
| ------ | ------ |
|
|
4132
|
+
| A | B |
|
|
4133
|
+
| B | E |
|
|
4134
|
+
|
|
4135
|
+
The generated IDs identify the connections in the result:
|
|
4136
|
+
|
|
4137
|
+
```ts
|
|
4138
|
+
await unnumberedConnections
|
|
4139
|
+
.addId("edgeId", { prefix: "edge-" })
|
|
4140
|
+
.shortestPath("source", "target", "edgeId", "A", "E")
|
|
4141
|
+
.log();
|
|
4142
|
+
```
|
|
4143
|
+
|
|
4144
|
+
| pathId | step | weight | total | source | target | edgeId |
|
|
4145
|
+
| -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4146
|
+
| 0 | 1 | 1 | 1 | A | B | edge-0 |
|
|
4147
|
+
| 0 | 2 | 1 | 2 | B | E | edge-1 |
|
|
4148
|
+
|
|
4149
|
+
The next two examples each start with these flights. The direct flight takes ten
|
|
4150
|
+
minutes; the route through B and D takes three:
|
|
4151
|
+
|
|
4152
|
+
| flightId | origin | destination | minutes |
|
|
4153
|
+
| -------- | ------ | ----------- | ------: |
|
|
4154
|
+
| F1 | A | E | 10 |
|
|
4155
|
+
| F2 | A | B | 1 |
|
|
4156
|
+
| F3 | B | D | 1 |
|
|
4157
|
+
| F4 | D | E | 1 |
|
|
4158
|
+
|
|
4159
|
+
With `weight: "minutes"`, the route with the shortest travel time is chosen:
|
|
4160
|
+
|
|
4161
|
+
```ts
|
|
4162
|
+
await flights
|
|
4163
|
+
.shortestPath("origin", "destination", "flightId", "A", "E", {
|
|
4164
|
+
weight: "minutes",
|
|
4165
|
+
})
|
|
4166
|
+
.log();
|
|
4167
|
+
```
|
|
4168
|
+
|
|
4169
|
+
| pathId | step | weight | total | flightId | origin | destination | minutes |
|
|
4170
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------: |
|
|
4171
|
+
| 0 | 1 | 1 | 1 | F2 | A | B | 1 |
|
|
4172
|
+
| 0 | 2 | 1 | 2 | F3 | B | D | 1 |
|
|
4173
|
+
| 0 | 3 | 1 | 3 | F4 | D | E | 1 |
|
|
4174
|
+
|
|
4175
|
+
Without the `weight` option, the direct flight is shortest because it uses only
|
|
4176
|
+
one connection:
|
|
4177
|
+
|
|
4178
|
+
```ts
|
|
4179
|
+
await flights
|
|
4180
|
+
.shortestPath("origin", "destination", "flightId", "A", "E")
|
|
4181
|
+
.log();
|
|
4182
|
+
```
|
|
4183
|
+
|
|
4184
|
+
| pathId | step | weight | total | flightId | origin | destination | minutes |
|
|
4185
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------: |
|
|
4186
|
+
| 0 | 1 | 1 | 1 | F1 | A | E | 10 |
|
|
4187
|
+
|
|
4188
|
+
With time options, the cheaper route through B is ruled out because F2 leaves
|
|
4189
|
+
before F1 arrives. The route through C meets the one-hour minimum gap:
|
|
4190
|
+
|
|
4191
|
+
| flightId | origin | destination | departureTime | arrivalTime | cost |
|
|
4192
|
+
| -------- | ------ | ----------- | ---------------- | ---------------- | ---: |
|
|
4193
|
+
| F1 | A | B | 2025-01-01 08:00 | 2025-01-01 10:00 | 1 |
|
|
4194
|
+
| F2 | B | E | 2025-01-01 09:00 | 2025-01-01 10:00 | 1 |
|
|
4195
|
+
| F3 | A | C | 2025-01-01 08:00 | 2025-01-01 09:00 | 2 |
|
|
4196
|
+
| F4 | C | E | 2025-01-01 10:00 | 2025-01-01 11:00 | 2 |
|
|
4197
|
+
|
|
4198
|
+
```ts
|
|
4199
|
+
await scheduledFlights
|
|
4200
|
+
.shortestPath("origin", "destination", "flightId", "A", "E", {
|
|
4201
|
+
startTimeColumn: "departureTime",
|
|
4202
|
+
endTimeColumn: "arrivalTime",
|
|
4203
|
+
minGapMs: 60 * 60 * 1000,
|
|
4204
|
+
weight: "cost",
|
|
4205
|
+
})
|
|
4206
|
+
.log();
|
|
4207
|
+
```
|
|
4208
|
+
|
|
4209
|
+
| pathId | step | weight | total | flightId | origin | destination | departureTime | arrivalTime | cost |
|
|
4210
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------------------- | ------------------- | ---: |
|
|
4211
|
+
| 0 | 1 | 2 | 2 | F3 | A | C | 2025-01-01 08:00:00 | 2025-01-01 09:00:00 | 2 |
|
|
4212
|
+
| 0 | 2 | 2 | 4 | F4 | C | E | 2025-01-01 10:00:00 | 2025-01-01 11:00:00 | 2 |
|
|
4213
|
+
|
|
4214
|
+
With `direction: "incoming"`, connections are followed from target to source.
|
|
4215
|
+
The original source and target values remain unchanged. For this input:
|
|
4216
|
+
|
|
4217
|
+
| edgeId | source | target |
|
|
4218
|
+
| ------ | ------ | ------ |
|
|
4219
|
+
| F1 | A | B |
|
|
4220
|
+
|
|
4221
|
+
```ts
|
|
4222
|
+
await reverseExample
|
|
4223
|
+
.shortestPath("source", "target", "edgeId", "B", "A", {
|
|
4224
|
+
direction: "incoming",
|
|
4225
|
+
})
|
|
4226
|
+
.log();
|
|
4227
|
+
```
|
|
4228
|
+
|
|
4229
|
+
| pathId | step | weight | total | edgeId | source | target |
|
|
4230
|
+
| -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4231
|
+
| 0 | 1 | 1 | 1 | F1 | A | B |
|
|
4232
|
+
|
|
4233
|
+
#### `paths`
|
|
4234
|
+
|
|
4235
|
+
Finds all routes between two different nodes. A route cannot visit the same node
|
|
4236
|
+
twice, to avoid loops. Different routes can still share the same nodes.
|
|
4237
|
+
|
|
4238
|
+
The `direction` option lets you follow connections from source to target, from
|
|
4239
|
+
target to source, or in either direction.
|
|
4240
|
+
|
|
4241
|
+
Each connection needs a unique, non-null ID. Pass the name of the column
|
|
4242
|
+
containing these IDs as the `edgeId` argument. If your table is missing an ID
|
|
4243
|
+
column, you can easily create one with `addId()`.
|
|
4244
|
+
|
|
4245
|
+
The result starts with the `pathId`, `step`, `weight`, and `total` columns,
|
|
4246
|
+
followed by all original columns. Steps start at one and follow the search
|
|
4247
|
+
direction. The `weight` column is the connection cost, and `total` is the sum of
|
|
4248
|
+
those costs up to and including the current step. Without the `weight` option,
|
|
4249
|
+
each connection costs one.
|
|
4250
|
+
|
|
4251
|
+
If an input column is already named `pathId`, `step`, `weight`, or `total`
|
|
4252
|
+
(regardless of capitalization), the method throws an error. Rename it with
|
|
4253
|
+
`renameColumns()` first.
|
|
4254
|
+
|
|
4255
|
+
Each row is one connection along a route.
|
|
4256
|
+
|
|
4257
|
+
Use the `startTimeColumn` or `endTimeColumn` options to follow connections in
|
|
4258
|
+
chronological order. The `minGapMs` option sets the minimum gap between
|
|
4259
|
+
consecutive connections, in milliseconds. With both time columns, gaps are
|
|
4260
|
+
measured from one connection's end to the next connection's start; with one
|
|
4261
|
+
column, between their timestamps. The `strictOrdering` option defaults to
|
|
4262
|
+
`true`, rejecting zero-duration gaps. These options only work with
|
|
4263
|
+
`direction: "outgoing"` or `direction: "incoming"`.
|
|
4264
|
+
|
|
4265
|
+
The minimum gap applies only between consecutive connections, not before the
|
|
4266
|
+
first connection.
|
|
4267
|
+
|
|
4268
|
+
Routes are numbered from zero by comparing their sequences of connection IDs,
|
|
4269
|
+
element by element. Rows are sorted by `pathId`, then `step`.
|
|
4270
|
+
|
|
4271
|
+
Unknown IDs or nodes with no route between them produce no rows. The start and
|
|
4272
|
+
end must differ. Self-connections are ignored. Weights must be non-null, finite,
|
|
4273
|
+
and non-negative.
|
|
4274
|
+
|
|
4275
|
+
There is no limit on route length or the number of routes returned. Finding all
|
|
4276
|
+
routes can take a long time and use substantial memory.
|
|
4277
|
+
|
|
4278
|
+
For the first example, we start with these connections:
|
|
4279
|
+
|
|
4280
|
+
| edgeId | source | target |
|
|
4281
|
+
| ------ | ------ | ------ |
|
|
4282
|
+
| E1 | A | B |
|
|
4283
|
+
| E2 | A | C |
|
|
4284
|
+
| E3 | B | D |
|
|
4285
|
+
| E4 | C | D |
|
|
4286
|
+
|
|
4287
|
+
By default, connections are followed from source to target. Both routes from A
|
|
4288
|
+
to D are returned:
|
|
4289
|
+
|
|
4290
|
+
##### Signature
|
|
4291
|
+
|
|
4292
|
+
```typescript
|
|
4293
|
+
paths(sourceColumn: string, targetColumn: string, edgeId: string, start: string | number | bigint, end: string | number | bigint, options?: { direction?: "outgoing" | "incoming" | "both"; endTimeColumn?: string; minGapMs?: number; outputTable?: string | boolean; startTimeColumn?: string; strictOrdering?: boolean; weight?: string }): SimpleTable;
|
|
4294
|
+
```
|
|
4295
|
+
|
|
4296
|
+
##### Parameters
|
|
4297
|
+
|
|
4298
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
4299
|
+
node ID.
|
|
4300
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
4301
|
+
node ID.
|
|
4302
|
+
- **`edgeId`**: The name of the column uniquely identifying each connection
|
|
4303
|
+
(edge).
|
|
4304
|
+
- **`start`**: The starting node ID.
|
|
4305
|
+
- **`end`**: The ending node ID, which must differ from `start`.
|
|
4306
|
+
- **`options`**: An optional object with direction, time, and result
|
|
4307
|
+
configuration.
|
|
4308
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
4309
|
+
Defaults to `"outgoing"`.
|
|
4310
|
+
- **`options.startTimeColumn`**: The name of the column containing each
|
|
4311
|
+
connection's start time. Use this or `endTimeColumn` to follow connections in
|
|
4312
|
+
chronological order.
|
|
4313
|
+
- **`options.endTimeColumn`**: The name of the column containing each
|
|
4314
|
+
connection's end time. Use this or `startTimeColumn` to follow connections in
|
|
4315
|
+
chronological order.
|
|
4316
|
+
- **`options.minGapMs`**: The minimum gap between consecutive connections, in
|
|
4317
|
+
milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time
|
|
4318
|
+
column.
|
|
4319
|
+
- **`options.strictOrdering`**: Whether to reject zero-duration gaps between
|
|
4320
|
+
consecutive connections (equal timestamps). Defaults to `true`. Requires a
|
|
4321
|
+
time column.
|
|
4322
|
+
- **`options.weight`**: The name of the numeric column used as the cost of each
|
|
4323
|
+
connection. If omitted, each connection costs one.
|
|
4324
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
4325
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
4326
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
4327
|
+
|
|
4328
|
+
##### Returns
|
|
4329
|
+
|
|
4330
|
+
The result table, so methods can be chained.
|
|
4331
|
+
|
|
4332
|
+
##### Examples
|
|
4333
|
+
|
|
4334
|
+
```ts
|
|
4335
|
+
await connections
|
|
4336
|
+
.paths("source", "target", "edgeId", "A", "D")
|
|
4337
|
+
.log();
|
|
4338
|
+
```
|
|
4339
|
+
|
|
4340
|
+
| pathId | step | weight | total | edgeId | source | target |
|
|
4341
|
+
| -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4342
|
+
| 0 | 1 | 1 | 1 | E1 | A | B |
|
|
4343
|
+
| 0 | 2 | 1 | 2 | E3 | B | D |
|
|
4344
|
+
| 1 | 1 | 1 | 1 | E2 | A | C |
|
|
4345
|
+
| 1 | 2 | 1 | 2 | E4 | C | D |
|
|
4346
|
+
|
|
4347
|
+
For an input without connection IDs, use `addId()` first:
|
|
4348
|
+
|
|
4349
|
+
| source | target |
|
|
4350
|
+
| ------ | ------ |
|
|
4351
|
+
| A | B |
|
|
4352
|
+
| B | D |
|
|
4353
|
+
|
|
4354
|
+
The generated IDs identify the connections in the result:
|
|
4355
|
+
|
|
4356
|
+
```ts
|
|
4357
|
+
await unnumberedConnections
|
|
4358
|
+
.addId("edgeId", { prefix: "edge-" })
|
|
4359
|
+
.paths("source", "target", "edgeId", "A", "D")
|
|
4360
|
+
.log();
|
|
4361
|
+
```
|
|
4362
|
+
|
|
4363
|
+
| pathId | step | weight | total | source | target | edgeId |
|
|
4364
|
+
| -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4365
|
+
| 0 | 1 | 1 | 1 | A | B | edge-0 |
|
|
4366
|
+
| 0 | 2 | 1 | 2 | B | D | edge-1 |
|
|
4367
|
+
|
|
4368
|
+
The next three examples each start with these flights. The direct flight takes
|
|
4369
|
+
ten minutes; the route through B takes three:
|
|
4370
|
+
|
|
4371
|
+
| flightId | origin | destination | minutes |
|
|
4372
|
+
| -------- | ------ | ----------- | ------: |
|
|
4373
|
+
| F1 | A | D | 10 |
|
|
4374
|
+
| F2 | A | B | 1 |
|
|
4375
|
+
| F3 | B | D | 2 |
|
|
4376
|
+
|
|
4377
|
+
With `weight: "minutes"`, both routes are returned with their travel times:
|
|
4378
|
+
|
|
4379
|
+
```ts
|
|
4380
|
+
await flights
|
|
4381
|
+
.paths("origin", "destination", "flightId", "A", "D", {
|
|
4382
|
+
weight: "minutes",
|
|
4383
|
+
})
|
|
4384
|
+
.log();
|
|
4385
|
+
```
|
|
4386
|
+
|
|
4387
|
+
| pathId | step | weight | total | flightId | origin | destination | minutes |
|
|
4388
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------: |
|
|
4389
|
+
| 0 | 1 | 10 | 10 | F1 | A | D | 10 |
|
|
4390
|
+
| 1 | 1 | 1 | 1 | F2 | A | B | 1 |
|
|
4391
|
+
| 1 | 2 | 2 | 3 | F3 | B | D | 2 |
|
|
4392
|
+
|
|
4393
|
+
Without the `weight` option, the same routes are returned and total counts
|
|
4394
|
+
connections:
|
|
4395
|
+
|
|
4396
|
+
```ts
|
|
4397
|
+
await flights
|
|
4398
|
+
.paths("origin", "destination", "flightId", "A", "D")
|
|
4399
|
+
.log();
|
|
4400
|
+
```
|
|
4401
|
+
|
|
4402
|
+
| pathId | step | weight | total | flightId | origin | destination | minutes |
|
|
4403
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------: |
|
|
4404
|
+
| 0 | 1 | 1 | 1 | F1 | A | D | 10 |
|
|
4405
|
+
| 1 | 1 | 1 | 1 | F2 | A | B | 1 |
|
|
4406
|
+
| 1 | 2 | 1 | 2 | F3 | B | D | 2 |
|
|
4407
|
+
|
|
4408
|
+
With `direction: "incoming"`, the search runs from D to A. Steps follow that
|
|
4409
|
+
direction, while the original origin and destination values stay unchanged:
|
|
4410
|
+
|
|
4411
|
+
```ts
|
|
4412
|
+
await flights
|
|
4413
|
+
.paths("origin", "destination", "flightId", "D", "A", {
|
|
4414
|
+
direction: "incoming",
|
|
4415
|
+
weight: "minutes",
|
|
4416
|
+
})
|
|
4417
|
+
.log();
|
|
4418
|
+
```
|
|
4419
|
+
|
|
4420
|
+
| pathId | step | weight | total | flightId | origin | destination | minutes |
|
|
4421
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------: |
|
|
4422
|
+
| 0 | 1 | 10 | 10 | F1 | A | D | 10 |
|
|
4423
|
+
| 1 | 1 | 2 | 2 | F3 | B | D | 2 |
|
|
4424
|
+
| 1 | 2 | 1 | 3 | F2 | A | B | 1 |
|
|
4425
|
+
|
|
4426
|
+
Chronological routes enforce the connection time between every pair of steps.
|
|
4427
|
+
For the next two examples, the 09:00 flight leaves before F1 arrives, while F3
|
|
4428
|
+
meets the one-hour minimum exactly:
|
|
4429
|
+
|
|
4430
|
+
| flightId | origin | destination | departureTime | arrivalTime | cost |
|
|
4431
|
+
| -------- | ------ | ----------- | ---------------- | ---------------- | ---: |
|
|
4432
|
+
| F1 | A | B | 2025-01-01 08:00 | 2025-01-01 10:00 | 2 |
|
|
4433
|
+
| F2 | B | C | 2025-01-01 09:00 | 2025-01-01 10:00 | 9 |
|
|
4434
|
+
| F3 | B | D | 2025-01-01 11:00 | 2025-01-01 12:00 | 3 |
|
|
4435
|
+
|
|
4436
|
+
The route from A to D contains F1 and F3:
|
|
4437
|
+
|
|
4438
|
+
```ts
|
|
4439
|
+
await scheduledFlights
|
|
4440
|
+
.paths("origin", "destination", "flightId", "A", "D", {
|
|
4441
|
+
startTimeColumn: "departureTime",
|
|
4442
|
+
endTimeColumn: "arrivalTime",
|
|
4443
|
+
minGapMs: 60 * 60 * 1000,
|
|
4444
|
+
weight: "cost",
|
|
4445
|
+
})
|
|
4446
|
+
.log();
|
|
4447
|
+
```
|
|
4448
|
+
|
|
4449
|
+
| pathId | step | weight | total | flightId | origin | destination | departureTime | arrivalTime | cost |
|
|
4450
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------------------- | ------------------- | ---: |
|
|
4451
|
+
| 0 | 1 | 2 | 2 | F1 | A | B | 2025-01-01 08:00:00 | 2025-01-01 10:00:00 | 2 |
|
|
4452
|
+
| 0 | 2 | 3 | 5 | F3 | B | D | 2025-01-01 11:00:00 | 2025-01-01 12:00:00 | 3 |
|
|
4453
|
+
|
|
4454
|
+
Searching backward from D finds the same physical journey. The steps and
|
|
4455
|
+
cumulative totals follow the incoming search from D to A:
|
|
4456
|
+
|
|
4457
|
+
```ts
|
|
4458
|
+
await scheduledFlights
|
|
4459
|
+
.paths("origin", "destination", "flightId", "D", "A", {
|
|
4460
|
+
direction: "incoming",
|
|
4461
|
+
startTimeColumn: "departureTime",
|
|
4462
|
+
endTimeColumn: "arrivalTime",
|
|
4463
|
+
minGapMs: 60 * 60 * 1000,
|
|
4464
|
+
weight: "cost",
|
|
4465
|
+
})
|
|
4466
|
+
.log();
|
|
4467
|
+
```
|
|
4468
|
+
|
|
4469
|
+
| pathId | step | weight | total | flightId | origin | destination | departureTime | arrivalTime | cost |
|
|
4470
|
+
| -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------------------- | ------------------- | ---: |
|
|
4471
|
+
| 0 | 1 | 3 | 3 | F3 | B | D | 2025-01-01 11:00:00 | 2025-01-01 12:00:00 | 3 |
|
|
4472
|
+
| 0 | 2 | 2 | 5 | F1 | A | B | 2025-01-01 08:00:00 | 2025-01-01 10:00:00 | 2 |
|
|
4473
|
+
|
|
4474
|
+
#### `findCycles`
|
|
4475
|
+
|
|
4476
|
+
Finds all cycles starting and ending at each node in `startNodes`. Pass one node
|
|
4477
|
+
ID or an array of node IDs. A cycle cannot visit the same node twice, except to
|
|
4478
|
+
return to its start, or reuse a connection. Different cycles can share nodes.
|
|
4479
|
+
The `direction` option lets you follow connections from source to target, from
|
|
4480
|
+
target to source, or in either direction. By default, connections are followed
|
|
4481
|
+
from source to target.
|
|
4482
|
+
|
|
4483
|
+
Each connection needs a unique, non-null ID. Pass the name of the column
|
|
4484
|
+
containing these IDs as the `edgeId` argument. If your table is missing an ID
|
|
4485
|
+
column, you can easily create one with `addId()`.
|
|
4486
|
+
|
|
4487
|
+
The result starts with the `start`, `pathId`, `step`, `weight`, and `total`
|
|
4488
|
+
columns, followed by all original columns. The `start` column identifies the
|
|
4489
|
+
requested starting node. Steps start at one and follow the search direction. The
|
|
4490
|
+
`weight` column is the connection cost, and `total` is the sum of those costs up
|
|
4491
|
+
to and including the current step. Without the `weight` option, each connection
|
|
4492
|
+
costs one.
|
|
4493
|
+
|
|
4494
|
+
If an input column is already named `start`, `pathId`, `step`, `weight`, or
|
|
4495
|
+
`total` (regardless of capitalization), the method throws an error. Rename it
|
|
4496
|
+
with `renameColumns()` first.
|
|
4497
|
+
|
|
4498
|
+
Each row is one connection, including the final connection back to the start.
|
|
4499
|
+
Weights must be non-null, finite, and non-negative.
|
|
4500
|
+
|
|
4501
|
+
If a cycle can start at several requested nodes, each starting node produces a
|
|
4502
|
+
separate result. The `pathId` starts at zero for each starting node; `start` and
|
|
4503
|
+
`pathId` together identify a cycle. Passing an empty array or duplicate IDs in
|
|
4504
|
+
`startNodes` throws an error. Unknown IDs or starts with no cycles produce no
|
|
4505
|
+
rows.
|
|
4506
|
+
|
|
4507
|
+
With `direction: "both"`, a cycle and its reverse are returned once per starting
|
|
4508
|
+
node, choosing the smaller sequence of connection IDs. Within each start, cycles
|
|
4509
|
+
are numbered by connection-ID sequence. Rows are sorted by `start`, then
|
|
4510
|
+
`pathId`, then `step`.
|
|
4511
|
+
|
|
4512
|
+
Use the `startTimeColumn` or `endTimeColumn` options to follow connections in
|
|
4513
|
+
chronological order. The `minGapMs` option sets the minimum gap between
|
|
4514
|
+
consecutive connections, in milliseconds. With both time columns, gaps are
|
|
4515
|
+
measured from one connection's end to the next connection's start; with one
|
|
4516
|
+
column, between their timestamps. The `strictOrdering` option defaults to
|
|
4517
|
+
`true`, rejecting zero-duration gaps. These options only work with
|
|
4518
|
+
`direction: "outgoing"` or `direction: "incoming"`.
|
|
4519
|
+
|
|
4520
|
+
Time rules are checked from each requested starting node. A cycle may therefore
|
|
4521
|
+
work from one starting node but not another. No gap is checked from the final
|
|
4522
|
+
connection back to the first. Incoming searches follow connections backward in
|
|
4523
|
+
chronological order.
|
|
4524
|
+
|
|
4525
|
+
A self-connection forms a one-step cycle. With `direction: "both"`, two separate
|
|
4526
|
+
connections between the same nodes can form a two-step cycle. A single
|
|
4527
|
+
connection cannot be followed out and back to create a cycle. Cycles using
|
|
4528
|
+
different connections remain separate, even if they visit the same nodes. If
|
|
4529
|
+
there are no cycles, the result has no rows.
|
|
4530
|
+
|
|
4531
|
+
There is no limit on cycle length or the number of cycles returned. Finding all
|
|
4532
|
+
cycles can take a long time and use substantial memory.
|
|
4533
|
+
|
|
4534
|
+
The next four examples each start with these connections:
|
|
4535
|
+
|
|
4536
|
+
| edgeId | source | target |
|
|
4537
|
+
| ------ | ------ | ------ |
|
|
4538
|
+
| E1 | A | B |
|
|
4539
|
+
| E2 | B | C |
|
|
4540
|
+
| E3 | C | A |
|
|
4541
|
+
|
|
4542
|
+
By default, connections are followed from source to target:
|
|
4543
|
+
|
|
4544
|
+
##### Signature
|
|
4545
|
+
|
|
4546
|
+
```typescript
|
|
4547
|
+
findCycles(sourceColumn: string, targetColumn: string, edgeId: string, startNodes: string | number | bigint | (string | number | bigint)[], options?: { direction?: "outgoing" | "incoming" | "both"; endTimeColumn?: string; minGapMs?: number; outputTable?: string | boolean; startTimeColumn?: string; strictOrdering?: boolean; weight?: string }): SimpleTable;
|
|
4548
|
+
```
|
|
4549
|
+
|
|
4550
|
+
##### Parameters
|
|
4551
|
+
|
|
4552
|
+
- **`sourceColumn`**: The name of the column containing each connection's source
|
|
4553
|
+
node ID.
|
|
4554
|
+
- **`targetColumn`**: The name of the column containing each connection's target
|
|
4555
|
+
node ID.
|
|
4556
|
+
- **`edgeId`**: The name of the column uniquely identifying each connection
|
|
4557
|
+
(edge).
|
|
4558
|
+
- **`startNodes`**: One starting node ID or an array of IDs. Finds cycles that
|
|
4559
|
+
start and end at each requested node.
|
|
4560
|
+
- **`options`**: An optional object with direction, time, cost, and result
|
|
4561
|
+
configuration.
|
|
4562
|
+
- **`options.direction`**: The direction in which to follow connections.
|
|
4563
|
+
Defaults to `"outgoing"`.
|
|
4564
|
+
- **`options.startTimeColumn`**: The name of the column containing each
|
|
4565
|
+
connection's start time. Use this or `endTimeColumn` to follow connections in
|
|
4566
|
+
chronological order.
|
|
4567
|
+
- **`options.endTimeColumn`**: The name of the column containing each
|
|
4568
|
+
connection's end time. Use this or `startTimeColumn` to follow connections in
|
|
4569
|
+
chronological order.
|
|
4570
|
+
- **`options.minGapMs`**: The minimum gap between consecutive connections, in
|
|
4571
|
+
milliseconds. Must be a non-negative integer. Defaults to `0`. Requires a time
|
|
4572
|
+
column.
|
|
4573
|
+
- **`options.strictOrdering`**: Whether to reject zero-duration gaps between
|
|
4574
|
+
consecutive connections (equal timestamps). Defaults to `true`. Requires a
|
|
4575
|
+
time column.
|
|
4576
|
+
- **`options.weight`**: The name of the numeric column used as the cost of each
|
|
4577
|
+
connection. If omitted, each connection costs one.
|
|
4578
|
+
- **`options.outputTable`**: If `true`, stores the result in a new table with a
|
|
4579
|
+
generated name. If a string, uses it as the new table's name. If `false` or
|
|
4580
|
+
omitted, overwrites the current table. Defaults to `false`.
|
|
4581
|
+
|
|
4582
|
+
##### Returns
|
|
4583
|
+
|
|
4584
|
+
The result table, so methods can be chained.
|
|
4585
|
+
|
|
4586
|
+
##### Examples
|
|
4587
|
+
|
|
4588
|
+
```ts
|
|
4589
|
+
await triangle
|
|
4590
|
+
.findCycles("source", "target", "edgeId", "A")
|
|
4591
|
+
.log();
|
|
4592
|
+
```
|
|
4593
|
+
|
|
4594
|
+
| start | pathId | step | weight | total | edgeId | source | target |
|
|
4595
|
+
| ----- | -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4596
|
+
| A | 0 | 1 | 1 | 1 | E1 | A | B |
|
|
4597
|
+
| A | 0 | 2 | 1 | 2 | E2 | B | C |
|
|
4598
|
+
| A | 0 | 3 | 1 | 3 | E3 | C | A |
|
|
4599
|
+
|
|
4600
|
+
Requesting both A and B returns the cycle separately for each start:
|
|
4601
|
+
|
|
4602
|
+
```ts
|
|
4603
|
+
await triangle
|
|
4604
|
+
.findCycles("source", "target", "edgeId", ["A", "B"])
|
|
4605
|
+
.log();
|
|
4606
|
+
```
|
|
4607
|
+
|
|
4608
|
+
| start | pathId | step | weight | total | edgeId | source | target |
|
|
4609
|
+
| ----- | -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4610
|
+
| A | 0 | 1 | 1 | 1 | E1 | A | B |
|
|
4611
|
+
| A | 0 | 2 | 1 | 2 | E2 | B | C |
|
|
4612
|
+
| A | 0 | 3 | 1 | 3 | E3 | C | A |
|
|
4613
|
+
| B | 0 | 1 | 1 | 1 | E2 | B | C |
|
|
4614
|
+
| B | 0 | 2 | 1 | 2 | E3 | C | A |
|
|
4615
|
+
| B | 0 | 3 | 1 | 3 | E1 | A | B |
|
|
4616
|
+
|
|
4617
|
+
With `direction: "incoming"`, connections are followed from target to source:
|
|
4618
|
+
|
|
4619
|
+
```ts
|
|
4620
|
+
await triangle
|
|
4621
|
+
.findCycles("source", "target", "edgeId", "A", { direction: "incoming" })
|
|
4622
|
+
.log();
|
|
4623
|
+
```
|
|
4624
|
+
|
|
4625
|
+
| start | pathId | step | weight | total | edgeId | source | target |
|
|
4626
|
+
| ----- | -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4627
|
+
| A | 0 | 1 | 1 | 1 | E3 | C | A |
|
|
4628
|
+
| A | 0 | 2 | 1 | 2 | E2 | B | C |
|
|
4629
|
+
| A | 0 | 3 | 1 | 3 | E1 | A | B |
|
|
4630
|
+
|
|
4631
|
+
With `direction: "both"`, either direction is allowed. This cycle appears once,
|
|
4632
|
+
in the direction that starts with E1:
|
|
4633
|
+
|
|
4634
|
+
```ts
|
|
4635
|
+
await triangle
|
|
4636
|
+
.findCycles("source", "target", "edgeId", "A", { direction: "both" })
|
|
4637
|
+
.log();
|
|
4638
|
+
```
|
|
4639
|
+
|
|
4640
|
+
| start | pathId | step | weight | total | edgeId | source | target |
|
|
4641
|
+
| ----- | -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4642
|
+
| A | 0 | 1 | 1 | 1 | E1 | A | B |
|
|
4643
|
+
| A | 0 | 2 | 1 | 2 | E2 | B | C |
|
|
4644
|
+
| A | 0 | 3 | 1 | 3 | E3 | C | A |
|
|
4645
|
+
|
|
4646
|
+
Two separate connections between A and B form a cycle with `direction:
|
|
4647
|
+
"both"`.
|
|
4648
|
+
The self-connection at C forms another cycle. For this input:
|
|
4649
|
+
|
|
4650
|
+
| edgeId | source | target | cost |
|
|
4651
|
+
| ------ | ------ | ------ | ---: |
|
|
4652
|
+
| P1 | A | B | 1 |
|
|
4653
|
+
| P2 | A | B | 2 |
|
|
4654
|
+
| L1 | C | C | 4 |
|
|
4655
|
+
|
|
4656
|
+
```ts
|
|
4657
|
+
await parallelAndLoop
|
|
4658
|
+
.findCycles("source", "target", "edgeId", ["A", "C"], {
|
|
4659
|
+
direction: "both",
|
|
4660
|
+
weight: "cost",
|
|
4661
|
+
})
|
|
4662
|
+
.log();
|
|
4663
|
+
```
|
|
4664
|
+
|
|
4665
|
+
| start | pathId | step | weight | total | edgeId | source | target | cost |
|
|
4666
|
+
| ----- | -----: | ---: | -----: | ----: | ------ | ------ | ------ | ---: |
|
|
4667
|
+
| A | 0 | 1 | 1 | 1 | P1 | A | B | 1 |
|
|
4668
|
+
| A | 0 | 2 | 2 | 3 | P2 | A | B | 2 |
|
|
4669
|
+
| C | 0 | 1 | 4 | 4 | L1 | C | C | 4 |
|
|
4670
|
+
|
|
4671
|
+
With the `weight` option, total is a running total of the selected values. For
|
|
4672
|
+
these flights:
|
|
4673
|
+
|
|
4674
|
+
| flightId | origin | destination | minutes |
|
|
4675
|
+
| -------- | ------ | ----------- | ------: |
|
|
4676
|
+
| F1 | A | B | 1 |
|
|
4677
|
+
| F2 | B | C | 2 |
|
|
4678
|
+
| F3 | C | A | 3 |
|
|
4679
|
+
|
|
4680
|
+
```ts
|
|
4681
|
+
await flights
|
|
4682
|
+
.findCycles("origin", "destination", "flightId", "A", {
|
|
4683
|
+
weight: "minutes",
|
|
4684
|
+
})
|
|
4685
|
+
.log();
|
|
4686
|
+
```
|
|
4687
|
+
|
|
4688
|
+
| start | pathId | step | weight | total | flightId | origin | destination | minutes |
|
|
4689
|
+
| ----- | -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------: |
|
|
4690
|
+
| A | 0 | 1 | 1 | 1 | F1 | A | B | 1 |
|
|
4691
|
+
| A | 0 | 2 | 2 | 3 | F2 | B | C | 2 |
|
|
4692
|
+
| A | 0 | 3 | 3 | 6 | F3 | C | A | 3 |
|
|
4693
|
+
|
|
4694
|
+
For an input without connection IDs, use `addId()` first:
|
|
4695
|
+
|
|
4696
|
+
| source | target |
|
|
4697
|
+
| ------ | ------ |
|
|
4698
|
+
| A | B |
|
|
4699
|
+
| B | C |
|
|
4700
|
+
| C | A |
|
|
4701
|
+
|
|
4702
|
+
```ts
|
|
4703
|
+
await unnumberedConnections
|
|
4704
|
+
.addId("edgeId", { prefix: "edge-" })
|
|
4705
|
+
.findCycles("source", "target", "edgeId", "A")
|
|
4706
|
+
.log();
|
|
4707
|
+
```
|
|
4708
|
+
|
|
4709
|
+
| start | pathId | step | weight | total | source | target | edgeId |
|
|
4710
|
+
| ----- | -----: | ---: | -----: | ----: | ------ | ------ | ------ |
|
|
4711
|
+
| A | 0 | 1 | 1 | 1 | A | B | edge-0 |
|
|
4712
|
+
| A | 0 | 2 | 1 | 2 | B | C | edge-1 |
|
|
4713
|
+
| A | 0 | 3 | 1 | 3 | C | A | edge-2 |
|
|
4714
|
+
|
|
4715
|
+
For these instantaneous events, requesting A and B as starting nodes returns
|
|
4716
|
+
only the cycle B → C → A → B. Starting at A would break chronological order:
|
|
4717
|
+
|
|
4718
|
+
| flightId | origin | destination | departureTime |
|
|
4719
|
+
| -------- | ------ | ----------- | ---------------- |
|
|
4720
|
+
| F1 | B | C | 2025-01-01 09:00 |
|
|
4721
|
+
| F2 | C | A | 2025-01-01 10:00 |
|
|
4722
|
+
| F3 | A | B | 2025-01-01 11:00 |
|
|
4723
|
+
|
|
4724
|
+
```ts
|
|
4725
|
+
await timedFlights
|
|
4726
|
+
.findCycles("origin", "destination", "flightId", ["A", "B"], {
|
|
4727
|
+
startTimeColumn: "departureTime",
|
|
4728
|
+
})
|
|
4729
|
+
.log();
|
|
4730
|
+
```
|
|
4731
|
+
|
|
4732
|
+
| start | pathId | step | weight | total | flightId | origin | destination | departureTime |
|
|
4733
|
+
| ----- | -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------------------- |
|
|
4734
|
+
| B | 0 | 1 | 1 | 1 | F1 | B | C | 2025-01-01 09:00:00 |
|
|
4735
|
+
| B | 0 | 2 | 1 | 2 | F2 | C | A | 2025-01-01 10:00:00 |
|
|
4736
|
+
| B | 0 | 3 | 1 | 3 | F3 | A | B | 2025-01-01 11:00:00 |
|
|
4737
|
+
|
|
4738
|
+
Searching the same events from B in the incoming direction follows connections
|
|
4739
|
+
backward, from the latest to the earliest:
|
|
4740
|
+
|
|
4741
|
+
```ts
|
|
4742
|
+
await timedFlights
|
|
4743
|
+
.findCycles("origin", "destination", "flightId", "B", {
|
|
4744
|
+
direction: "incoming",
|
|
4745
|
+
startTimeColumn: "departureTime",
|
|
4746
|
+
})
|
|
4747
|
+
.log();
|
|
4748
|
+
```
|
|
4749
|
+
|
|
4750
|
+
| start | pathId | step | weight | total | flightId | origin | destination | departureTime |
|
|
4751
|
+
| ----- | -----: | ---: | -----: | ----: | -------- | ------ | ----------- | ------------------- |
|
|
4752
|
+
| B | 0 | 1 | 1 | 1 | F3 | A | B | 2025-01-01 11:00:00 |
|
|
4753
|
+
| B | 0 | 2 | 1 | 2 | F2 | C | A | 2025-01-01 10:00:00 |
|
|
4754
|
+
| B | 0 | 3 | 1 | 3 | F1 | B | C | 2025-01-01 09:00:00 |
|
|
4755
|
+
|
|
4756
|
+
#### `extractDatePart`
|
|
4757
|
+
|
|
4758
|
+
Extracts one or more components from a temporal column into new columns. Pass a
|
|
4759
|
+
single part to create a column with that part's name, or pass an object mapping
|
|
4760
|
+
custom new-column names to parts. Existing columns are not overwritten.
|
|
4761
|
+
|
|
4762
|
+
`dayOfWeek` uses Sunday as `0` through Saturday as `6`. `week` follows ISO week
|
|
4763
|
+
numbering, and `dayOfYear` starts at `1`. DuckDB `DATE`, `TIME`, `TIMESTAMP`,
|
|
4764
|
+
and `TIMESTAMP WITH TIME ZONE` columns are supported when the requested
|
|
4765
|
+
component applies to that type: date parts apply to dates and timestamps, while
|
|
4766
|
+
time parts apply to times and timestamps. `NULL` input values produce `NULL`
|
|
4767
|
+
extracted values. Parts extracted from `TIMESTAMP WITH TIME ZONE` values use
|
|
4768
|
+
UTC.
|
|
4769
|
+
|
|
4770
|
+
##### Signature
|
|
4771
|
+
|
|
4772
|
+
```typescript
|
|
4773
|
+
extractDatePart(column: string, parts: "year" | "quarter" | "month" | "week" | "day" | "dayOfWeek" | "dayOfYear" | "hour" | "minute" | "second" | Record<string, "year" | "quarter" | "month" | "week" | "day" | "dayOfWeek" | "dayOfYear" | "hour" | "minute" | "second">): this;
|
|
4774
|
+
```
|
|
4775
|
+
|
|
4776
|
+
##### Parameters
|
|
4777
|
+
|
|
4778
|
+
- **`column`**: The temporal column from which to extract components.
|
|
4779
|
+
- **`parts`**: A part to extract using its name as the new column, or an object
|
|
4780
|
+
mapping each custom new-column name to the part it should contain.
|
|
4781
|
+
|
|
4782
|
+
##### Returns
|
|
4783
|
+
|
|
4784
|
+
The table, so methods can be chained.
|
|
4785
|
+
|
|
4786
|
+
##### Examples
|
|
4787
|
+
|
|
4788
|
+
```ts
|
|
4789
|
+
// Add a column named 'year' from the 'publishedAt' timestamp
|
|
4790
|
+
await table.extractDatePart("publishedAt", "year").log();
|
|
4791
|
+
```
|
|
4792
|
+
|
|
4793
|
+
```ts
|
|
4794
|
+
// Extract multiple components with custom column names
|
|
4795
|
+
await table.extractDatePart("publishedAt", {
|
|
4796
|
+
publicationYear: "year",
|
|
4797
|
+
publicationMonth: "month",
|
|
4798
|
+
}).log();
|
|
4799
|
+
```
|
|
4800
|
+
|
|
4801
|
+
#### `addRowNumber`
|
|
4802
|
+
|
|
4803
|
+
Adds a new column to the table containing the row number, starting at 0 (like an
|
|
4804
|
+
index).
|
|
4805
|
+
|
|
4806
|
+
##### Signature
|
|
4807
|
+
|
|
4808
|
+
```typescript
|
|
4809
|
+
addRowNumber(newColumn: string, options?: { by?: string | string[] }): this;
|
|
4810
|
+
```
|
|
4811
|
+
|
|
4812
|
+
##### Parameters
|
|
4813
|
+
|
|
4814
|
+
- **`newColumn`**: The name of the new column that will store the row number.
|
|
4815
|
+
- **`options`**: An optional object with configuration options:
|
|
4816
|
+
- **`options.by`**: A column name or an array of column names to partition by.
|
|
4817
|
+
The row number restarts at 0 within each group.
|
|
4818
|
+
|
|
4819
|
+
##### Returns
|
|
4820
|
+
|
|
4821
|
+
The table, so methods can be chained.
|
|
4822
|
+
|
|
4823
|
+
##### Examples
|
|
4824
|
+
|
|
4825
|
+
```ts
|
|
4826
|
+
// Add a new column named 'rowNumber' with the row number for each row
|
|
4827
|
+
await table.addRowNumber("rowNumber").log();
|
|
4828
|
+
```
|
|
4829
|
+
|
|
4830
|
+
```ts
|
|
4831
|
+
// Add a new column named 'rowNumber' with the row number for each 'category'
|
|
4832
|
+
await table.addRowNumber("rowNumber", { by: "category" }).log();
|
|
4833
|
+
```
|
|
4834
|
+
|
|
4835
|
+
#### `crossJoin`
|
|
4836
|
+
|
|
4837
|
+
Performs a cross join operation with another table. A cross join returns the
|
|
4838
|
+
Cartesian product of the rows from both tables, meaning all possible pairs of
|
|
4839
|
+
rows will be in the resulting table. This means that if the left table has `n`
|
|
4840
|
+
rows and the right table has `m` rows, the result will have `n * m` rows.
|
|
4841
|
+
|
|
4842
|
+
##### Signature
|
|
4843
|
+
|
|
4844
|
+
```typescript
|
|
4845
|
+
crossJoin(rightTable: SimpleTable, options?: { outputTable?: string | boolean }): this;
|
|
4846
|
+
```
|
|
4847
|
+
|
|
4848
|
+
##### Parameters
|
|
4849
|
+
|
|
4850
|
+
- **`rightTable`**: The SimpleTable instance to cross join with.
|
|
4851
|
+
- **`options`**: An optional object with configuration options:
|
|
4852
|
+
- **`options.outputTable`**: If `true`, the results will be stored in a new
|
|
4853
|
+
table with a generated name. If a string, it will be used as the name for the
|
|
4854
|
+
new table. If `false` or omitted, the current table will be overwritten.
|
|
4855
|
+
Defaults to `false`.
|
|
4856
|
+
|
|
4857
|
+
##### Returns
|
|
4858
|
+
|
|
4859
|
+
A table instance containing the cross-joined data (either the current table or a
|
|
4860
|
+
new table), so methods can be chained.
|
|
4861
|
+
|
|
4862
|
+
##### Examples
|
|
4863
|
+
|
|
4864
|
+
```ts
|
|
4865
|
+
// Perform a cross join with 'tableB', overwriting the current table (tableA)
|
|
4866
|
+
await tableA.crossJoin(tableB).log();
|
|
4867
|
+
```
|
|
4868
|
+
|
|
4869
|
+
```ts
|
|
4870
|
+
// Perform a cross join with 'tableB' and store the results in a new table with a generated name
|
|
4871
|
+
const tableC = await tableA.crossJoin(tableB, { outputTable: true }).log();
|
|
4872
|
+
```
|
|
4873
|
+
|
|
4874
|
+
```ts
|
|
4875
|
+
// Perform a cross join with 'tableB' and store the results in a new table named 'tableC'
|
|
4876
|
+
const tableC = await tableA.crossJoin(tableB, { outputTable: "tableC" }).log();
|
|
4877
|
+
```
|
|
4878
|
+
|
|
4879
|
+
#### `join`
|
|
4880
|
+
|
|
4881
|
+
Merges the data of this table (considered the left table) with another table
|
|
4882
|
+
(the right table) based on a common column or multiple columns. Note that the
|
|
4883
|
+
order of rows in the returned data is not guaranteed to be the same as in the
|
|
4884
|
+
original tables. This operation might create temporary files in a `.tmp` folder;
|
|
4885
|
+
consider adding `.tmp` to your `.gitignore`.
|
|
4886
|
+
|
|
4887
|
+
##### Signature
|
|
4888
|
+
|
|
4889
|
+
```typescript
|
|
4890
|
+
join(rightTable: SimpleTable, options?: { on?: string | string[]; type?: "inner" | "left" | "right" | "full"; outputTable?: string | boolean }): this;
|
|
4891
|
+
```
|
|
4892
|
+
|
|
4893
|
+
##### Parameters
|
|
4894
|
+
|
|
4895
|
+
- **`rightTable`**: The SimpleTable instance to be joined with this table.
|
|
4896
|
+
- **`options`**: An optional object with configuration options:
|
|
4897
|
+
- **`options.on`**: The column(s) to join on. If omitted, the method
|
|
4898
|
+
automatically searches for a column name that exists in both tables. Can be a
|
|
4899
|
+
single string or an array of strings for multiple join keys.
|
|
4900
|
+
- **`options.type`**: The type of join operation to perform. Possible values are
|
|
4901
|
+
`"inner"`, `"left"` (default), `"right"`, or `"full"`.
|
|
4902
|
+
- **`options.outputTable`**: If `true`, the results will be stored in a new
|
|
4903
|
+
table with a generated name. If a string, it will be used as the name for the
|
|
4904
|
+
new table. If `false` or omitted, the current table will be overwritten.
|
|
4905
|
+
Defaults to `false`.
|
|
4906
|
+
|
|
4907
|
+
##### Returns
|
|
4908
|
+
|
|
4909
|
+
A table instance containing the joined data (either the current table or a new
|
|
4910
|
+
table), so methods can be chained.
|
|
4911
|
+
|
|
4912
|
+
##### Examples
|
|
4913
|
+
|
|
4914
|
+
```ts
|
|
4915
|
+
// Perform a left join with 'tableB' on a common column (auto-detected), overwriting tableA
|
|
4916
|
+
await tableA.join(tableB).log();
|
|
4917
|
+
```
|
|
4918
|
+
|
|
4919
|
+
```ts
|
|
4920
|
+
// Perform an inner join with 'tableB' on the 'id' column, storing results in a new table named 'tableC'
|
|
4921
|
+
const tableC = await tableA.join(tableB, {
|
|
4922
|
+
on: "id",
|
|
4923
|
+
type: "inner",
|
|
4924
|
+
outputTable: "tableC",
|
|
4925
|
+
}).log();
|
|
4926
|
+
```
|
|
4927
|
+
|
|
4928
|
+
```ts
|
|
4929
|
+
// Perform a join on multiple columns ('name' and 'category')
|
|
4930
|
+
await tableA.join(tableB, { on: ["name", "category"] }).log();
|
|
4931
|
+
```
|
|
4932
|
+
|
|
4933
|
+
#### `fuzzyJoin`
|
|
4934
|
+
|
|
4935
|
+
Performs a fuzzy left join between this table (considered the left table) and
|
|
4936
|
+
another table (the right table) based on string similarity between two text
|
|
4937
|
+
columns. Uses the [rapidfuzz](https://query.farm/duckdb_extension_rapidfuzz)
|
|
4938
|
+
DuckDB community extension.
|
|
4939
|
+
|
|
4940
|
+
If a similarity score column is added to the results, the rows will be ordered
|
|
4941
|
+
alphabetically by the left column, and then by descending similarity score
|
|
4942
|
+
within each group of identical left column values. Otherwise, the rows will be
|
|
4943
|
+
order alphabetically by the left column and then by the right column.
|
|
4944
|
+
|
|
4945
|
+
This operation might create temporary files in a `.tmp` folder; consider adding
|
|
4946
|
+
`.tmp` to your `.gitignore`.
|
|
4947
|
+
|
|
4948
|
+
##### Signature
|
|
4949
|
+
|
|
4950
|
+
```typescript
|
|
4951
|
+
fuzzyJoin(rightTable: SimpleTable, leftColumn: string, rightColumn: string, threshold: number, options?: { method?: "ratio" | "partial_ratio" | "token_sort_ratio" | "token_set_ratio"; similarityColumn?: string; outputTable?: string | boolean; prefilterPrefixLength?: number }): this;
|
|
4952
|
+
```
|
|
4953
|
+
|
|
4954
|
+
##### Parameters
|
|
4955
|
+
|
|
4956
|
+
- **`rightTable`**: The SimpleTable instance to be joined with this table.
|
|
4957
|
+
- **`leftColumn`**: The name of the column in this (left) table containing the
|
|
4958
|
+
text to compare.
|
|
4959
|
+
- **`rightColumn`**: The name of the column in the right table containing the
|
|
4960
|
+
text to compare.
|
|
4961
|
+
- **`threshold`**: The minimum similarity score (0–100) required for two rows to
|
|
4962
|
+
be joined. For `method: "ratio"`, a length-based pre-filter is automatically
|
|
4963
|
+
applied based on the threshold to improve performance without losing accuracy.
|
|
4964
|
+
- **`options`**: An optional object with configuration options:
|
|
4965
|
+
- **`options.method`**: The rapidfuzz similarity algorithm to use. Defaults to
|
|
4966
|
+
`"ratio"`. - `"ratio"`: Overall similarity (Levenshtein-based). -
|
|
4967
|
+
`"partial_ratio"`: Best partial/substring similarity. - `"token_sort_ratio"`:
|
|
4968
|
+
Similarity after sorting tokens (words), useful for reordered words. -
|
|
4969
|
+
`"token_set_ratio"`: Similarity based on sets of tokens, ignoring duplicates
|
|
4970
|
+
and word order.
|
|
4971
|
+
- **`options.similarityColumn`**: If provided, a column with this name is added
|
|
4972
|
+
to the result containing the similarity score (0–100). If omitted, the score
|
|
4973
|
+
is not included in the output.
|
|
4974
|
+
- **`options.outputTable`**: If `true`, the results will be stored in a new
|
|
4975
|
+
table with a generated name. If a string, it will be used as the name for the
|
|
4976
|
+
new table. If `false` or omitted, the current table will be overwritten.
|
|
4977
|
+
Defaults to `false`.
|
|
4978
|
+
- **`options.prefilterPrefixLength`**: An optional prefix length. Only strings
|
|
4979
|
+
sharing the same first N characters are compared. Note that prefix filtering
|
|
4980
|
+
is lossy (e.g. "John" vs. "Phon" will not match despite high similarity).
|
|
4981
|
+
|
|
4982
|
+
##### Returns
|
|
4983
|
+
|
|
4984
|
+
A table instance containing the fuzzy-joined data (either the current table or a
|
|
4985
|
+
new table), so methods can be chained.
|
|
4986
|
+
|
|
4987
|
+
##### Examples
|
|
4988
|
+
|
|
4989
|
+
```ts
|
|
4990
|
+
// Fuzzy left join tableA with tableB on 'name' (left) and 'standardName' (right) with a threshold of 80
|
|
4991
|
+
// A length-based pre-filter is automatically applied.
|
|
4992
|
+
await tableA.fuzzyJoin(tableB, "name", "standardName", 80).log();
|
|
4993
|
+
```
|
|
4994
|
+
|
|
4995
|
+
```ts
|
|
4996
|
+
// Fuzzy join with a prefix-based pre-filter and a threshold of 80
|
|
4997
|
+
await tableA.fuzzyJoin(tableB, "name", "standardName", 80, {
|
|
4998
|
+
prefilterPrefixLength: 3, // Must share the same first 3 characters
|
|
4999
|
+
}).log();
|
|
5000
|
+
```
|
|
5001
|
+
|
|
5002
|
+
```ts
|
|
5003
|
+
// Fuzzy join with a custom threshold and method, storing results in a new table
|
|
5004
|
+
const tableC = await tableA.fuzzyJoin(tableB, "name", "standardName", 90, {
|
|
5005
|
+
method: "token_sort_ratio",
|
|
5006
|
+
outputTable: "tableC",
|
|
5007
|
+
}).log();
|
|
5008
|
+
```
|
|
5009
|
+
|
|
5010
|
+
```ts
|
|
5011
|
+
// Fuzzy join with a custom similarity column name and a threshold of 80
|
|
5012
|
+
await tableA.fuzzyJoin(tableB, "name", "standardName", 80, {
|
|
5013
|
+
similarityColumn: "matchScore",
|
|
5014
|
+
}).log();
|
|
5015
|
+
```
|
|
5016
|
+
|
|
5017
|
+
#### `fuzzyClean`
|
|
5018
|
+
|
|
5019
|
+
Normalizes string values in a column by detecting fuzzy duplicates and replacing
|
|
5020
|
+
them with a single canonical value.
|
|
5021
|
+
|
|
5022
|
+
Similar strings are grouped into clusters. Matching is transitive: if
|
|
5023
|
+
`"New York"` is similar to `"New Yorke"` and `"New Yorke"` is similar to
|
|
5024
|
+
`"New Yorkk"`, all three land in the same cluster even if `"New York"` and
|
|
5025
|
+
`"New Yorkk"` would not match directly. Each cluster is then collapsed to one
|
|
5026
|
+
representative value based on the `strategy` option.
|
|
5027
|
+
|
|
5028
|
+
Similarity is computed using the
|
|
5029
|
+
[rapidfuzz](https://query.farm/duckdb_extension_rapidfuzz) DuckDB community
|
|
5030
|
+
extension, which is installed and loaded automatically.
|
|
5031
|
+
|
|
5032
|
+
##### Signature
|
|
5033
|
+
|
|
5034
|
+
```typescript
|
|
5035
|
+
fuzzyClean(column: string, newColumn: string, threshold: number, options?: { method?: "ratio" | "partial_ratio" | "token_sort_ratio" | "token_set_ratio"; strategy?: "mostCommon" | "longestString" | "shortestString" | "mostCentral" | "maxScore"; prefilterPrefixLength?: number }): this;
|
|
5036
|
+
```
|
|
5037
|
+
|
|
5038
|
+
##### Parameters
|
|
5039
|
+
|
|
5040
|
+
- **`column`**: The name of the column containing the strings to normalize.
|
|
5041
|
+
- **`newColumn`**: The name of the column to write the normalized values to. Use
|
|
5042
|
+
the same name as `column` to normalize in-place.
|
|
3218
5043
|
- **`threshold`**: The minimum similarity score (0–100) for two strings to be
|
|
3219
5044
|
considered duplicates. For `method: "ratio"`, a length-based pre-filter is
|
|
3220
5045
|
automatically applied based on the threshold to improve performance without
|
|
@@ -3273,7 +5098,8 @@ await table.fuzzyClean("category", "category", 80, {
|
|
|
3273
5098
|
|
|
3274
5099
|
#### `replace`
|
|
3275
5100
|
|
|
3276
|
-
Replaces specified strings in the selected columns.
|
|
5101
|
+
Replaces specified strings in the selected columns. Use `["all"]` to target a
|
|
5102
|
+
column literally named `all`.
|
|
3277
5103
|
|
|
3278
5104
|
##### Signature
|
|
3279
5105
|
|
|
@@ -3656,7 +5482,8 @@ await table.lastChars("productCode", 2).log();
|
|
|
3656
5482
|
|
|
3657
5483
|
#### `replaceNulls`
|
|
3658
5484
|
|
|
3659
|
-
Replaces `NULL` values in the specified columns with a given value.
|
|
5485
|
+
Replaces `NULL` values in the specified columns with a given value. Use
|
|
5486
|
+
`["all"]` to target a column literally named `all`.
|
|
3660
5487
|
|
|
3661
5488
|
##### Signature
|
|
3662
5489
|
|
|
@@ -3796,6 +5623,152 @@ await table
|
|
|
3796
5623
|
.rowToText(["name", "age", "salary"], "profile").log();
|
|
3797
5624
|
```
|
|
3798
5625
|
|
|
5626
|
+
#### `rowToVector`
|
|
5627
|
+
|
|
5628
|
+
Combines numeric scalar columns into a fixed-size vector. The input column order
|
|
5629
|
+
determines the vector dimension order, and null values remain null vector
|
|
5630
|
+
elements.
|
|
5631
|
+
|
|
5632
|
+
When all input columns have the same numeric type, that type is preserved. Mixed
|
|
5633
|
+
numeric types require an explicit `type` option. Casting exact decimals or large
|
|
5634
|
+
integers to FLOAT or DOUBLE can lose precision.
|
|
5635
|
+
|
|
5636
|
+
##### Signature
|
|
5637
|
+
|
|
5638
|
+
```typescript
|
|
5639
|
+
rowToVector(columns: string[], newColumn: string, options?: { type?: "float" | "double" }): this;
|
|
5640
|
+
```
|
|
5641
|
+
|
|
5642
|
+
##### Parameters
|
|
5643
|
+
|
|
5644
|
+
- **`columns`**: Numeric scalar columns to combine, in vector dimension order.
|
|
5645
|
+
- **`newColumn`**: The name of the vector column to create.
|
|
5646
|
+
- **`options`**: Optional vector element type settings.
|
|
5647
|
+
- **`options.type`**: Cast every element to `"float"` or `"double"`. Required
|
|
5648
|
+
when the input column types differ.
|
|
5649
|
+
|
|
5650
|
+
##### Returns
|
|
5651
|
+
|
|
5652
|
+
The table, so methods can be chained.
|
|
5653
|
+
|
|
5654
|
+
##### Examples
|
|
5655
|
+
|
|
5656
|
+
```ts
|
|
5657
|
+
await table
|
|
5658
|
+
.rowToVector(["height", "weight"], "measurements")
|
|
5659
|
+
.log();
|
|
5660
|
+
```
|
|
5661
|
+
|
|
5662
|
+
```ts
|
|
5663
|
+
await table
|
|
5664
|
+
.rowToVector(["count", "score"], "features", { type: "double" })
|
|
5665
|
+
.log();
|
|
5666
|
+
```
|
|
5667
|
+
|
|
5668
|
+
#### `normalizeVector`
|
|
5669
|
+
|
|
5670
|
+
Normalizes a numeric vector column. By default, each dimension is scaled
|
|
5671
|
+
independently to `[0, 1]` across rows: all first elements together, all second
|
|
5672
|
+
elements together, and so on. With `normalization: "rowL2"`, each row is scaled
|
|
5673
|
+
to Euclidean unit length while preserving its direction; zero vectors remain
|
|
5674
|
+
zero.
|
|
5675
|
+
|
|
5676
|
+
The input may be a numeric LIST or fixed-size ARRAY. The output is a fixed-size
|
|
5677
|
+
DOUBLE ARRAY. Converting large integers and exact decimals to DOUBLE can lose
|
|
5678
|
+
precision. With `"dimensionMinMax"`, a dimension whose converted values are all
|
|
5679
|
+
equal cannot be normalized.
|
|
5680
|
+
|
|
5681
|
+
##### Signature
|
|
5682
|
+
|
|
5683
|
+
```typescript
|
|
5684
|
+
normalizeVector(column: string, newColumn: string, options?: { normalization?: "dimensionMinMax" | "rowL2" }): this;
|
|
5685
|
+
```
|
|
5686
|
+
|
|
5687
|
+
##### Parameters
|
|
5688
|
+
|
|
5689
|
+
- **`column`**: The numeric vector column to normalize.
|
|
5690
|
+
- **`newColumn`**: The output column. Use the source column's name to replace
|
|
5691
|
+
the source column with the normalized DOUBLE vector.
|
|
5692
|
+
- **`options`**: Normalization settings.
|
|
5693
|
+
- **`options.normalization`**: `"dimensionMinMax"` scales each dimension across
|
|
5694
|
+
rows; `"rowL2"` scales each row to unit length. Defaults to
|
|
5695
|
+
`"dimensionMinMax"`.
|
|
5696
|
+
|
|
5697
|
+
##### Returns
|
|
5698
|
+
|
|
5699
|
+
The table, so methods can be chained.
|
|
5700
|
+
|
|
5701
|
+
##### Examples
|
|
5702
|
+
|
|
5703
|
+
```ts
|
|
5704
|
+
// Scale each dimension across rows to [0, 1] in a new column.
|
|
5705
|
+
await table
|
|
5706
|
+
.normalizeVector("features", "scaledFeatures")
|
|
5707
|
+
.log();
|
|
5708
|
+
```
|
|
5709
|
+
|
|
5710
|
+
```ts
|
|
5711
|
+
// Replace each vector with its unit-length version; zero vectors stay zero.
|
|
5712
|
+
await table
|
|
5713
|
+
.normalizeVector("features", "features", { normalization: "rowL2" })
|
|
5714
|
+
.log();
|
|
5715
|
+
```
|
|
5716
|
+
|
|
5717
|
+
#### `mahalanobis`
|
|
5718
|
+
|
|
5719
|
+
Calculates each row's Mahalanobis distance from a supplied reference point and
|
|
5720
|
+
stores it in a new DOUBLE column. Sample covariance (`n - 1`) is estimated from
|
|
5721
|
+
the dataset, independently of the reference point.
|
|
5722
|
+
|
|
5723
|
+
Pass one numeric LIST or ARRAY column, or an array of numeric scalar columns.
|
|
5724
|
+
Reference values follow the same dimension order. Inputs are converted privately
|
|
5725
|
+
to DOUBLE, which can lose precision for large integers and exact decimals;
|
|
5726
|
+
source columns and types remain unchanged.
|
|
5727
|
+
|
|
5728
|
+
Requires more rows than dimensions and finite, non-null, consistent features
|
|
5729
|
+
with invertible, numerically stable covariance. Invalid inputs leave the source
|
|
5730
|
+
unchanged.
|
|
5731
|
+
|
|
5732
|
+
##### Signature
|
|
5733
|
+
|
|
5734
|
+
```typescript
|
|
5735
|
+
mahalanobis(columns: string | string[], referencePoint: number[], newColumn: string, options?: { similarityScoreColumn?: string }): this;
|
|
5736
|
+
```
|
|
5737
|
+
|
|
5738
|
+
##### Parameters
|
|
5739
|
+
|
|
5740
|
+
- **`columns`**: A numeric vector column, or numeric scalar columns in feature
|
|
5741
|
+
order.
|
|
5742
|
+
- **`referencePoint`**: One finite number per feature dimension; may be outside
|
|
5743
|
+
the dataset.
|
|
5744
|
+
- **`newColumn`**: The name of the new DOUBLE distance column.
|
|
5745
|
+
- **`options`**: Optional output settings.
|
|
5746
|
+
- **`options.similarityScoreColumn`**: A new DOUBLE column for the
|
|
5747
|
+
dataset-relative score `1 - distance / maxDistance`. Exact matches score 1 and
|
|
5748
|
+
the farthest rows score 0; if all distances are zero, every score is 1.
|
|
5749
|
+
|
|
5750
|
+
##### Returns
|
|
5751
|
+
|
|
5752
|
+
The table, so methods can be chained.
|
|
5753
|
+
|
|
5754
|
+
##### Examples
|
|
5755
|
+
|
|
5756
|
+
```ts
|
|
5757
|
+
// Measure distance from a reference height and weight.
|
|
5758
|
+
await table
|
|
5759
|
+
.mahalanobis(["height", "weight"], [175, 70], "distance")
|
|
5760
|
+
.log();
|
|
5761
|
+
```
|
|
5762
|
+
|
|
5763
|
+
```ts
|
|
5764
|
+
// Compare feature vectors and add a dataset-relative similarity score.
|
|
5765
|
+
await table
|
|
5766
|
+
.mahalanobis("features", [175, 70], "distance", {
|
|
5767
|
+
similarityScoreColumn: "similarity",
|
|
5768
|
+
})
|
|
5769
|
+
.log();
|
|
5770
|
+
```
|
|
5771
|
+
|
|
3799
5772
|
#### `unnest`
|
|
3800
5773
|
|
|
3801
5774
|
Unnests (expands) rows by splitting a column's string values into multiple rows
|