Skip to content

Commit 7077fbe

Browse files
committed
feat: provide alternative array notation for nested paths
Closes #432
1 parent a3892ec commit 7077fbe

12 files changed

Lines changed: 356 additions & 152 deletions

File tree

dist/fuse.js

Lines changed: 111 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -269,53 +269,33 @@
269269

270270
_classCallCheck(this, KeyStore);
271271

272-
this._keys = {};
273-
this._keyNames = [];
272+
this._keys = [];
273+
this._keyMap = {};
274274
var totalWeight = 0;
275275
keys.forEach(function (key) {
276-
var keyName;
277-
var weight = 1;
276+
var obj = createKey(key);
277+
totalWeight += obj.weight;
278278

279-
if (isString(key)) {
280-
keyName = key;
281-
} else {
282-
if (!hasOwn.call(key, 'name')) {
283-
throw new Error(MISSING_KEY_PROPERTY('name'));
284-
}
285-
286-
keyName = key.name;
287-
288-
if (hasOwn.call(key, 'weight')) {
289-
weight = key.weight;
279+
_this._keys.push(obj);
290280

291-
if (weight <= 0) {
292-
throw new Error(INVALID_KEY_WEIGHT_VALUE(keyName));
293-
}
294-
}
295-
}
296-
297-
_this._keyNames.push(keyName);
298-
299-
_this._keys[keyName] = {
300-
weight: weight
301-
};
302-
totalWeight += weight;
281+
_this._keyMap[obj.id] = obj;
282+
totalWeight += obj.weight;
303283
}); // Normalize weights so that their sum is equal to 1
304284

305-
this._keyNames.forEach(function (key) {
306-
_this._keys[key].weight /= totalWeight;
285+
this._keys.forEach(function (key) {
286+
key.weight /= totalWeight;
307287
});
308288
}
309289

310290
_createClass(KeyStore, [{
311291
key: "get",
312-
value: function get(key, name) {
313-
return this._keys[key] && this._keys[key][name];
292+
value: function get(keyId) {
293+
return this._keyMap[keyId];
314294
}
315295
}, {
316296
key: "keys",
317297
value: function keys() {
318-
return this._keyNames;
298+
return this._keys;
319299
}
320300
}, {
321301
key: "toJSON",
@@ -326,47 +306,82 @@
326306

327307
return KeyStore;
328308
}();
309+
function createKey(key) {
310+
var path = null;
311+
var id = null;
312+
var src = null;
313+
var weight = 1;
314+
315+
if (isString(key) || isArray(key)) {
316+
src = key;
317+
path = createKeyPath(key);
318+
id = createKeyId(key);
319+
} else {
320+
if (!hasOwn.call(key, 'name')) {
321+
throw new Error(MISSING_KEY_PROPERTY('name'));
322+
}
323+
324+
var name = key.name;
325+
src = name;
326+
327+
if (hasOwn.call(key, 'weight')) {
328+
weight = key.weight;
329+
330+
if (weight <= 0) {
331+
throw new Error(INVALID_KEY_WEIGHT_VALUE(name));
332+
}
333+
}
334+
335+
path = createKeyPath(name);
336+
id = createKeyId(name);
337+
}
338+
339+
return {
340+
path: path,
341+
id: id,
342+
weight: weight,
343+
src: src
344+
};
345+
}
346+
function createKeyPath(key) {
347+
return isArray(key) ? key : key.split('.');
348+
}
349+
function createKeyId(key) {
350+
return isArray(key) ? key.join('.') : key;
351+
}
329352

330353
function get(obj, path) {
331354
var list = [];
332355
var arr = false;
333356

334-
var deepGet = function deepGet(obj, path) {
335-
if (!path) {
357+
var deepGet = function deepGet(obj, path, index) {
358+
if (!path[index]) {
336359
// If there's no path left, we've arrived at the object we care about.
337360
list.push(obj);
338361
} else {
339-
var dotIndex = path.indexOf('.');
340-
var key = path;
341-
var remaining = null;
342-
343-
if (dotIndex !== -1) {
344-
key = path.slice(0, dotIndex);
345-
remaining = path.slice(dotIndex + 1);
346-
}
347-
362+
var key = path[index];
348363
var value = obj[key];
349364

350365
if (!isDefined(value)) {
351366
return;
352367
}
353368

354-
if (!remaining && (isString(value) || isNumber(value))) {
369+
if (index === path.length - 1 && (isString(value) || isNumber(value))) {
355370
list.push(toString(value));
356371
} else if (isArray(value)) {
357372
arr = true; // Search each item in the array.
358373

359374
for (var i = 0, len = value.length; i < len; i += 1) {
360-
deepGet(value[i], remaining);
375+
deepGet(value[i], path, index + 1);
361376
}
362-
} else if (remaining) {
377+
} else if (path.length) {
363378
// An object. Recurse further.
364-
deepGet(value, remaining);
379+
deepGet(value, path, index + 1);
365380
}
366381
}
367382
};
368383

369-
deepGet(obj, path);
384+
deepGet(obj, path, 0);
370385
return arr ? list : list[0];
371386
}
372387

@@ -479,13 +494,19 @@
479494
}, {
480495
key: "setKeys",
481496
value: function setKeys() {
497+
var _this = this;
498+
482499
var keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
483500
this.keys = keys;
501+
this._keysMap = {};
502+
keys.forEach(function (key, idx) {
503+
_this._keysMap[key.id] = idx;
504+
});
484505
}
485506
}, {
486507
key: "create",
487508
value: function create() {
488-
var _this = this;
509+
var _this2 = this;
489510

490511
if (this.isCreated || !this.docs.length) {
491512
return;
@@ -495,12 +516,12 @@
495516

496517
if (isString(this.docs[0])) {
497518
this.docs.forEach(function (doc, docIndex) {
498-
_this._addString(doc, docIndex);
519+
_this2._addString(doc, docIndex);
499520
});
500521
} else {
501522
// List is Array<Object>
502523
this.docs.forEach(function (doc, docIndex) {
503-
_this._addObject(doc, docIndex);
524+
_this2._addObject(doc, docIndex);
504525
});
505526
}
506527

@@ -528,6 +549,11 @@
528549
this.records[i].i -= 1;
529550
}
530551
}
552+
}, {
553+
key: "getValueForItemAtKeyId",
554+
value: function getValueForItemAtKeyId(item, keyId) {
555+
return item[this._keysMap[keyId]];
556+
}
531557
}, {
532558
key: "size",
533559
value: function size() {
@@ -550,15 +576,16 @@
550576
}, {
551577
key: "_addObject",
552578
value: function _addObject(doc, docIndex) {
553-
var _this2 = this;
579+
var _this3 = this;
554580

555581
var record = {
556582
i: docIndex,
557583
$: {}
558584
}; // Iterate over every key (i.e, path), and fetch the value at that key
559585

560586
this.keys.forEach(function (key, keyIndex) {
561-
var value = _this2.getFn(doc, key);
587+
// console.log(key)
588+
var value = _this3.getFn(doc, key.path);
562589

563590
if (!isDefined(value)) {
564591
return;
@@ -585,7 +612,7 @@
585612
var subRecord = {
586613
v: _value,
587614
i: nestedArrIndex,
588-
n: _this2.norm.get(_value)
615+
n: _this3.norm.get(_value)
589616
};
590617
subRecords.push(subRecord);
591618
} else if (isArray(_value)) {
@@ -603,7 +630,7 @@
603630
} else if (!isBlank(value)) {
604631
var subRecord = {
605632
v: value,
606-
n: _this2.norm.get(value)
633+
n: _this3.norm.get(value)
607634
};
608635
record.$[keyIndex] = subRecord;
609636
}
@@ -630,8 +657,9 @@
630657
var myIndex = new FuseIndex({
631658
getFn: getFn
632659
});
633-
var keyStore = new KeyStore(keys);
634-
myIndex.setKeys(keyStore.keys());
660+
myIndex.setKeys(keys.map(function (key) {
661+
return createKey(key);
662+
}));
635663
myIndex.setSources(docs);
636664
myIndex.create();
637665
return myIndex;
@@ -672,7 +700,7 @@
672700
};
673701

674702
if (match.key) {
675-
obj.key = match.key;
703+
obj.key = match.key.src;
676704
}
677705

678706
if (match.idx > -1) {
@@ -1664,11 +1692,19 @@
16641692
AND: '$and',
16651693
OR: '$or'
16661694
};
1695+
var KeyType = {
1696+
PATH: '$path',
1697+
PATTERN: '$val'
1698+
};
16671699

16681700
var isExpression = function isExpression(query) {
16691701
return !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]);
16701702
};
16711703

1704+
var isPath = function isPath(query) {
1705+
return !!query[KeyType.PATH];
1706+
};
1707+
16721708
var isLeaf = function isLeaf(query) {
16731709
return !isArray(query) && isObject(query) && !isExpression(query);
16741710
};
@@ -1688,22 +1724,22 @@
16881724

16891725
var next = function next(query) {
16901726
var keys = Object.keys(query);
1727+
var isQueryPath = isPath(query);
16911728

1692-
if (keys.length > 1 && !isExpression(query)) {
1729+
if (!isQueryPath && keys.length > 1 && !isExpression(query)) {
16931730
return next(convertToExplicit(query));
16941731
}
16951732

1696-
var key = keys[0];
1697-
16981733
if (isLeaf(query)) {
1699-
var pattern = query[key];
1734+
var key = isQueryPath ? query[KeyType.PATH] : keys[0];
1735+
var pattern = isQueryPath ? query[KeyType.PATTERN] : query[key];
17001736

17011737
if (!isString(pattern)) {
17021738
throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key));
17031739
}
17041740

17051741
var obj = {
1706-
key: key,
1742+
keyId: createKeyId(key),
17071743
pattern: pattern
17081744
};
17091745

@@ -1716,7 +1752,7 @@
17161752

17171753
var node = {
17181754
children: [],
1719-
operator: key
1755+
operator: keys[0]
17201756
};
17211757
keys.forEach(function (key) {
17221758
var value = query[key];
@@ -1763,7 +1799,7 @@
17631799
throw new Error(INCORRECT_INDEX_TYPE);
17641800
}
17651801

1766-
this._myIndex = index || createIndex(this._keyStore.keys(), this._docs, {
1802+
this._myIndex = index || createIndex(this.options.keys, this._docs, {
17671803
getFn: this.options.getFn
17681804
});
17691805
}
@@ -1886,9 +1922,7 @@
18861922
var _this = this;
18871923

18881924
var expression = parse(query, this.options);
1889-
var _this$_myIndex = this._myIndex,
1890-
keys = _this$_myIndex.keys,
1891-
records = _this$_myIndex.records;
1925+
var records = this._myIndex.records;
18921926
var resultMap = {};
18931927
var results = [];
18941928

@@ -1921,11 +1955,13 @@
19211955

19221956
return res;
19231957
} else {
1924-
var key = node.key,
1958+
var keyId = node.keyId,
19251959
searcher = node.searcher;
1926-
var value = item[keys.indexOf(key)];
1960+
1961+
var value = _this._myIndex.getValueForItemAtKeyId(item, keyId);
1962+
19271963
return _this._findMatches({
1928-
key: key,
1964+
key: _this._keyStore.get(keyId),
19291965
value: value,
19301966
searcher: searcher
19311967
});
@@ -1968,9 +2004,9 @@
19682004
var _this2 = this;
19692005

19702006
var searcher = createSearcher(query, this.options);
1971-
var _this$_myIndex2 = this._myIndex,
1972-
keys = _this$_myIndex2.keys,
1973-
records = _this$_myIndex2.records;
2007+
var _this$_myIndex = this._myIndex,
2008+
keys = _this$_myIndex.keys,
2009+
records = _this$_myIndex.records;
19742010
var results = []; // List is Array<Object>
19752011

19762012
records.forEach(function (_ref5) {
@@ -2076,7 +2112,7 @@
20762112
var key = _ref9.key,
20772113
norm = _ref9.norm,
20782114
score = _ref9.score;
2079-
var weight = keyStore.get(key, 'weight');
2115+
var weight = key ? key.weight : null;
20802116
totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm));
20812117
});
20822118
result.score = totalScore;

0 commit comments

Comments
 (0)