Comparing version 0.6.2 to 0.6.3
@@ -9,2 +9,4 @@ 'use strict'; | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -55,2 +57,4 @@ value: true | ||
var _Document = require('./Document'); | ||
var _DocumentRetriver = require('./DocumentRetriver'); | ||
@@ -86,2 +90,4 @@ | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
// UUID counter for all cursors | ||
@@ -103,2 +109,3 @@ var _currentCursorId = 0; | ||
JoinAll: 'JoinAll', | ||
JoinObj: 'JoinObj', | ||
IfNotEmpty: 'IfNotEmpty' | ||
@@ -118,3 +125,5 @@ }; | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.Join, function (docs, pipeObj, cursor) { | ||
if (_checkTypes2.default.array(docs)) { | ||
if (_checkTypes2.default.object(pipeObj.value)) { | ||
return PIPELINE_PROCESSORS[PIPELINE_TYPE.JoinObj](docs, pipeObj, cursor); | ||
} else if (_checkTypes2.default.array(docs)) { | ||
return PIPELINE_PROCESSORS[PIPELINE_TYPE.JoinEach](docs, pipeObj, cursor); | ||
@@ -154,2 +163,69 @@ } else { | ||
}); | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.JoinObj, function (docs, pipeObj, cursor) { | ||
var joinObj = pipeObj.value; | ||
var isObj = !_checkTypes2.default.array(docs); | ||
docs = !isObj ? docs : [docs]; | ||
var joinerFn = function joinerFn(dcs) { | ||
return (0, _map3.default)((0, _keys3.default)(joinObj), function (k) { | ||
var joinKey = k.split('.')[0]; | ||
var model = joinObj[k]; | ||
var lookupFn = (0, _DocumentMatcher.makeLookupFunction)(k); | ||
var childToRootMap = {}; | ||
var docsById = {}; | ||
var allIds = []; | ||
(0, _forEach2.default)(dcs, function (d) { | ||
docsById[d._id] = { d: d, isArray: false }; | ||
var val = lookupFn(d); | ||
var singleJoin = !val[0] || !val[0].arrayIndices; | ||
var joinIds = (0, _filter3.default)((0, _reduce3.default)((0, _map3.default)(val, function (x) { | ||
return x.value; | ||
}), function (a, b) { | ||
if (_checkTypes2.default.array(b)) { | ||
singleJoin = false; | ||
return [].concat(_toConsumableArray(a), _toConsumableArray(b)); | ||
} else { | ||
return [].concat(_toConsumableArray(a), [b]); | ||
} | ||
}, []), function (x) { | ||
return (0, _Document.selectorIsId)(x); | ||
}); | ||
allIds = allIds.concat(joinIds); | ||
docsById[d._id].isArray = !singleJoin; | ||
d[joinKey] = null; | ||
(0, _forEach2.default)(joinIds, function (joinId) { | ||
var localIdsMap = childToRootMap[joinId] || []; | ||
localIdsMap.push(d._id); | ||
childToRootMap[joinId] = localIdsMap; | ||
}); | ||
}); | ||
return model.find({ _id: { $in: allIds } }).observe(function (res) { | ||
(0, _forEach2.default)(res, function (objToJoin) { | ||
var docIdsForJoin = childToRootMap[objToJoin._id]; | ||
(0, _forEach2.default)(docIdsForJoin, function (docId) { | ||
var doc = docsById[docId]; | ||
if (doc) { | ||
var joinedVal = doc.d[joinKey] || (doc.isArray ? [] : null); | ||
if (doc.isArray) { | ||
joinedVal.push(objToJoin); | ||
} else { | ||
joinedVal = objToJoin; | ||
} | ||
doc.d[joinKey] = joinedVal; | ||
} | ||
}); | ||
}); | ||
}); | ||
}); | ||
}; | ||
var newPipeObj = _extends({}, pipeObj, { value: joinerFn }); | ||
return PIPELINE_PROCESSORS[PIPELINE_TYPE.JoinAll](docs, newPipeObj, cursor).then(function (res) { | ||
return isObj ? res[0] : res; | ||
}); | ||
}), _defineProperty(_PIPELINE_PROCESSORS, PIPELINE_TYPE.IfNotEmpty, function (docs) { | ||
@@ -275,3 +351,3 @@ var isEmptyRes = !_checkTypes2.default.assigned(docs) || _checkTypes2.default.array(docs) && _checkTypes2.default.emptyArray(docs) || _checkTypes2.default.object(docs) && _checkTypes2.default.emptyObject(docs); | ||
value: function join(joinFn) { | ||
(0, _invariant2.default)(typeof joinFn === 'function', 'join(...): argument must be a function'); | ||
(0, _invariant2.default)(typeof joinFn === 'function' || _checkTypes2.default.object(joinFn), 'join(...): argument must be a function'); | ||
@@ -298,2 +374,10 @@ this._addPipeline(PIPELINE_TYPE.Join, joinFn); | ||
}, { | ||
key: 'joinObj', | ||
value: function joinObj(obj) { | ||
(0, _invariant2.default)(_checkTypes2.default.object(obj), 'joinObj(...): argument must be an object'); | ||
this._addPipeline(PIPELINE_TYPE.JoinObj, obj); | ||
return this; | ||
} | ||
}, { | ||
key: 'ifNotEmpty', | ||
@@ -300,0 +384,0 @@ value: function ifNotEmpty() { |
@@ -26,2 +26,4 @@ 'use strict'; | ||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
@@ -117,3 +119,4 @@ | ||
var retrPromises = (0, _map3.default)(ids, function (id) { | ||
var uniqIds = [].concat(_toConsumableArray(new Set(ids))); | ||
var retrPromises = (0, _map3.default)(uniqIds, function (id) { | ||
return _this2.retriveOne(id); | ||
@@ -120,0 +123,0 @@ }); |
@@ -11,4 +11,5 @@ import _bind from 'fast.js/function/bind'; | ||
import invariant from 'invariant'; | ||
import { selectorIsId } from './Document'; | ||
import DocumentRetriver from './DocumentRetriver'; | ||
import DocumentMatcher from './DocumentMatcher'; | ||
import DocumentMatcher, { makeLookupFunction } from './DocumentMatcher'; | ||
import DocumentSorter from './DocumentSorter'; | ||
@@ -35,2 +36,3 @@ import DocumentProjector from './DocumentProjector'; | ||
JoinAll: 'JoinAll', | ||
JoinObj: 'JoinObj', | ||
IfNotEmpty: 'IfNotEmpty', | ||
@@ -56,3 +58,5 @@ }; | ||
[PIPELINE_TYPE.Join]: (docs, pipeObj, cursor) => { | ||
if (_check.array(docs)) { | ||
if (_check.object(pipeObj.value)) { | ||
return PIPELINE_PROCESSORS[PIPELINE_TYPE.JoinObj](docs, pipeObj, cursor); | ||
} else if (_check.array(docs)) { | ||
return PIPELINE_PROCESSORS[PIPELINE_TYPE.JoinEach](docs, pipeObj, cursor); | ||
@@ -93,2 +97,63 @@ } else { | ||
}, | ||
[PIPELINE_TYPE.JoinObj]: (docs, pipeObj, cursor) => { | ||
const joinObj = pipeObj.value; | ||
const isObj = !_check.array(docs); | ||
docs = !isObj ? docs : [docs]; | ||
const joinerFn = (dcs) => _map(_keys(joinObj), k => { | ||
const joinKey = k.split('.')[0]; | ||
const model = joinObj[k]; | ||
const lookupFn = makeLookupFunction(k); | ||
const childToRootMap = {}; | ||
const docsById = {}; | ||
let allIds = []; | ||
_each(dcs, (d) => { | ||
docsById[d._id] = { d, isArray: false }; | ||
const val = lookupFn(d); | ||
let singleJoin = !val[0] || !val[0].arrayIndices; | ||
const joinIds = _filter(_reduce(_map(val, x => x.value), (a, b) => { | ||
if (_check.array(b)) { | ||
singleJoin = false; | ||
return [...a, ...b]; | ||
} else { | ||
return [...a, b]; | ||
} | ||
}, []), x => selectorIsId(x)); | ||
allIds = allIds.concat(joinIds); | ||
docsById[d._id].isArray = !singleJoin; | ||
d[joinKey] = null; | ||
_each(joinIds, joinId => { | ||
const localIdsMap = childToRootMap[joinId] || []; | ||
localIdsMap.push(d._id); | ||
childToRootMap[joinId] = localIdsMap; | ||
}); | ||
}); | ||
return model.find({_id: {$in: allIds}}).observe(res => { | ||
_each(res, objToJoin => { | ||
const docIdsForJoin = childToRootMap[objToJoin._id]; | ||
_each(docIdsForJoin, docId => { | ||
const doc = docsById[docId]; | ||
if (doc) { | ||
let joinedVal = doc.d[joinKey] || (doc.isArray ? [] : null); | ||
if (doc.isArray) { | ||
joinedVal.push(objToJoin); | ||
} else { | ||
joinedVal = objToJoin; | ||
} | ||
doc.d[joinKey] = joinedVal; | ||
} | ||
}); | ||
}); | ||
}); | ||
}); | ||
const newPipeObj = { ...pipeObj, value: joinerFn }; | ||
return PIPELINE_PROCESSORS[PIPELINE_TYPE.JoinAll](docs, newPipeObj, cursor) | ||
.then(res => isObj ? res[0] : res); | ||
}, | ||
[PIPELINE_TYPE.IfNotEmpty]: (docs) => { | ||
@@ -223,3 +288,3 @@ const isEmptyRes = ( | ||
invariant( | ||
typeof joinFn === 'function', | ||
typeof joinFn === 'function' || _check.object(joinFn), | ||
'join(...): argument must be a function' | ||
@@ -252,2 +317,12 @@ ); | ||
joinObj(obj) { | ||
invariant( | ||
_check.object(obj), | ||
'joinObj(...): argument must be an object' | ||
); | ||
this._addPipeline(PIPELINE_TYPE.JoinObj, obj); | ||
return this; | ||
} | ||
ifNotEmpty() { | ||
@@ -254,0 +329,0 @@ this._addPipeline(PIPELINE_TYPE.IfNotEmpty); |
@@ -83,3 +83,4 @@ import _check from 'check-types'; | ||
retriveIds(ids) { | ||
const retrPromises = _map(ids, id => this.retriveOne(id)); | ||
const uniqIds = [...(new Set(ids))]; | ||
const retrPromises = _map(uniqIds, id => this.retriveOne(id)); | ||
return Promise.all(retrPromises).then((docs) => ( | ||
@@ -86,0 +87,0 @@ _filter(docs, (d) => d) |
{ | ||
"name": "marsdb", | ||
"version": "0.6.2", | ||
"version": "0.6.3", | ||
"author": { | ||
@@ -5,0 +5,0 @@ "name": "Artem Artemev", |
@@ -171,2 +171,5 @@ <div style="text-align:center"><img src="https://static.studytime.me/marsdb.png" /></div> | ||
}) | ||
// Or just pass join spec object for fast joining | ||
// (only one `find` will be produced for all posts) | ||
.join({ authorId: users }) // posts[i].authorId will be user object | ||
.observe((posts) => { | ||
@@ -173,0 +176,0 @@ // do something with posts with authors |
@@ -18,9 +18,9 @@ import Collection from '../../lib/Collection'; | ||
return Promise.all([ | ||
db.insert({a: 'a', b: 1, c: 'some text 1', g: 'g1', f: 1}), | ||
db.insert({a: 'b', b: 2, c: 'some text 2', g: 'g1', f: 10}), | ||
db.insert({a: 'c', b: 3, c: 'some text 3', g: 'g1', f: 11}), | ||
db.insert({a: 'd', b: 4, c: 'some text 4', g: 'g1', f: 12}), | ||
db.insert({a: 'e', b: 5, c: 'some text 5', g: 'g2', d: 234, f: 2}), | ||
db.insert({a: 'f', b: 6, c: 'some text 6', g: 'g2', f: 20, k: {a: 1}}), | ||
db.insert({a: 'g', b: 7, c: 'some text 7', g: 'g2', f: 21}), | ||
db.insert({_id: '1', a: 'a', b: 1, c: 'some text 1', g: 'g1', f: 1, j: '2'}), | ||
db.insert({_id: '2', a: 'b', b: 2, c: 'some text 2', g: 'g1', f: 10, j: '3'}), | ||
db.insert({_id: '3', a: 'c', b: 3, c: 'some text 3', g: 'g1', f: 11, j: '4'}), | ||
db.insert({_id: '4', a: 'd', b: 4, c: 'some text 4', g: 'g1', f: 12, j: '5'}), | ||
db.insert({_id: '5', a: 'e', b: 5, c: 'some text 5', g: 'g2', d: 234, f: 2, j: '6'}), | ||
db.insert({_id: '6', a: 'f', b: 6, c: 'some text 6', g: 'g2', f: 20, k: {a: 1}, j: ['7', '5']}), | ||
db.insert({_id: '7', a: 'g', b: 7, c: 'some text 7', g: 'g2', f: 21, j: [{_id: '1'}, {_id: '2'}]}), | ||
]); | ||
@@ -406,2 +406,12 @@ }); | ||
it('should joinObj for object value', function () { | ||
sinon.spy(db, 'find'); | ||
sinon.spy(db, 'findOne'); | ||
return db.findOne('1').join({j: db}).then(res => { | ||
db.find.should.be.calledOnce; | ||
db.findOne.should.be.calledOnce; | ||
res.j._id.should.be.equal('2'); | ||
}); | ||
}); | ||
it('should throw an error if join is not a function', function () { | ||
@@ -440,2 +450,46 @@ const cursor = new Cursor(db); | ||
describe('#joinObj', function () { | ||
it('should join for all docs only by one query call', function () { | ||
sinon.spy(db, 'find'); | ||
return db.find().sort(['_id']).joinObj({j: db}).then(res => { | ||
db.find.should.be.calledTwice; | ||
res[0].j._id.should.be.equal('2'); | ||
res[1].j._id.should.be.equal('3'); | ||
res[2].j._id.should.be.equal('4'); | ||
res[3].j._id.should.be.equal('5'); | ||
res[4].j._id.should.be.equal('6'); | ||
res[5].j.should.have.length(2); | ||
res[5].j[0]._id.should.be.equal('5'); | ||
res[5].j[1]._id.should.be.equal('7'); | ||
expect(res[6].j).to.be.null; | ||
}); | ||
}); | ||
it('should join for findOne', function () { | ||
sinon.spy(db, 'find'); | ||
sinon.spy(db, 'findOne'); | ||
return db.findOne('1').joinObj({j: db}).then(res => { | ||
db.find.should.be.calledOnce; | ||
db.findOne.should.be.calledOnce; | ||
res.j._id.should.be.equal('2'); | ||
}); | ||
}); | ||
it('should join with nested object', function () { | ||
sinon.spy(db, 'find'); | ||
return db.find().sort(['_id']).joinObj({'j._id': db}).then(res => { | ||
db.find.should.be.calledTwice; | ||
expect(res[0].j).to.be.null; | ||
expect(res[1].j).to.be.null; | ||
expect(res[2].j).to.be.null; | ||
expect(res[3].j).to.be.null; | ||
expect(res[4].j).to.be.null; | ||
expect(res[5].j).to.be.null; | ||
res[6].j.should.have.length(2); | ||
res[6].j[0]._id.should.be.equal('1'); | ||
res[6].j[1]._id.should.be.equal('2'); | ||
}); | ||
}); | ||
}); | ||
describe('#joinEach', function () { | ||
@@ -442,0 +496,0 @@ it('should join by function with promises', function () { |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
991532
22831
237