Last active
June 26, 2019 11:44
-
-
Save assafweinberg/4c7ef4e833d0493c693b to your computer and use it in GitHub Desktop.
SQL Join with LokiJS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import loki from 'lokijs'; | |
import _ from 'lodash'; | |
class relationalWrapper { | |
constructor(dbName) { | |
this.db = new loki('dbName'); | |
} | |
//Utility to strip loki meta data | |
_stripMetaData(obj) { | |
var returnValue = _.clone(obj); | |
delete returnValue.$loki; | |
delete returnValue.meta; | |
return returnValue; | |
} | |
/** | |
* Convenience method to create objects that contain fields from objects in two collections (like sql join) | |
* The objects returned are clones of the original, so updating them won't update the originals in the DB. | |
* @param left {String || ARRAY} name of left side collection or data array to use for left side | |
* @param right {String || ARRAY} name of right side collection or data array to use for right side | |
* @param joinField {String} name of property to join collections on. | |
* @param joinFieldRight {String} (optional) Name of the join property for the right side collection if supplied. If not supplied, joinField is used. | |
*/ | |
innerJoin(left, right, joinField, joinFieldRight) { | |
//Populate data for left array if only a collection name is specified | |
if(!Array.isArray(left)) { | |
var leftColl = this.db.getCollection(left); | |
left = leftColl.find(); | |
} | |
//If no left data, bail early | |
if(!left || left.length == 0) | |
return []; | |
//Strip metadata from left side | |
left = left.map((item)=>{ | |
return this._stripMetaData(item); | |
}); | |
//If no right join key is specified, use the left key | |
joinFieldRight = joinFieldRight || joinField; | |
//Get data for right array if only a collection name is specified | |
if(!Array.isArray(right)){ | |
var rightColl = this.db.getCollection(right); | |
right = rightColl.find(); | |
} | |
//if no right data, bail early by returning left data | |
if(!right || right.length == 0) | |
return _.cloneDeep(left); | |
//strip metadata from right side | |
right = right.map((item)=>{ | |
return this._stripMetaData(item); | |
}); | |
var results = []; | |
left.forEach((leftItem)=>{ | |
var leftKey = leftItem[joinField]; | |
let leftObj = _.assign({},leftItem); | |
//Get all matches in right table | |
var rightItems = right.filter((item)=>{ | |
return item[joinFieldRight] === leftKey; | |
}); | |
//If no right matches, just add the left item attributes | |
if(rightItems.length === 0){ | |
results.push(leftObj); | |
//Inner join - create a separate object for each match in the right column | |
} else { | |
rightItems.forEach((rightItem)=>{ | |
let combined = _.clone(leftObj) | |
for(var key in rightItem){ | |
var prefix = (leftObj.hasOwnProperty(key) && key !== joinField) ? "right_" : '' | |
combined[prefix + key] = rightItem[key]; | |
} | |
results.push(combined); | |
}); | |
} | |
}); | |
return results; | |
} | |
} | |
export default relationalWrapper; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Thank you for your gist !
Could you please provide a usage example ? because i was not able to use it ...
I do something like this ...
And i have the following error :
I would really appreciate a usage example ...
Regards
Remi