|
269 | 269 |
|
270 | 270 | _classCallCheck(this, KeyStore); |
271 | 271 |
|
272 | | - this._keys = {}; |
273 | | - this._keyNames = []; |
| 272 | + this._keys = []; |
| 273 | + this._keyMap = {}; |
274 | 274 | var totalWeight = 0; |
275 | 275 | keys.forEach(function (key) { |
276 | | - var keyName; |
277 | | - var weight = 1; |
| 276 | + var obj = createKey(key); |
| 277 | + totalWeight += obj.weight; |
278 | 278 |
|
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); |
290 | 280 |
|
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; |
303 | 283 | }); // Normalize weights so that their sum is equal to 1 |
304 | 284 |
|
305 | | - this._keyNames.forEach(function (key) { |
306 | | - _this._keys[key].weight /= totalWeight; |
| 285 | + this._keys.forEach(function (key) { |
| 286 | + key.weight /= totalWeight; |
307 | 287 | }); |
308 | 288 | } |
309 | 289 |
|
310 | 290 | _createClass(KeyStore, [{ |
311 | 291 | 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]; |
314 | 294 | } |
315 | 295 | }, { |
316 | 296 | key: "keys", |
317 | 297 | value: function keys() { |
318 | | - return this._keyNames; |
| 298 | + return this._keys; |
319 | 299 | } |
320 | 300 | }, { |
321 | 301 | key: "toJSON", |
|
326 | 306 |
|
327 | 307 | return KeyStore; |
328 | 308 | }(); |
| 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 | + } |
329 | 352 |
|
330 | 353 | function get(obj, path) { |
331 | 354 | var list = []; |
332 | 355 | var arr = false; |
333 | 356 |
|
334 | | - var deepGet = function deepGet(obj, path) { |
335 | | - if (!path) { |
| 357 | + var deepGet = function deepGet(obj, path, index) { |
| 358 | + if (!path[index]) { |
336 | 359 | // If there's no path left, we've arrived at the object we care about. |
337 | 360 | list.push(obj); |
338 | 361 | } 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]; |
348 | 363 | var value = obj[key]; |
349 | 364 |
|
350 | 365 | if (!isDefined(value)) { |
351 | 366 | return; |
352 | 367 | } |
353 | 368 |
|
354 | | - if (!remaining && (isString(value) || isNumber(value))) { |
| 369 | + if (index === path.length - 1 && (isString(value) || isNumber(value))) { |
355 | 370 | list.push(toString(value)); |
356 | 371 | } else if (isArray(value)) { |
357 | 372 | arr = true; // Search each item in the array. |
358 | 373 |
|
359 | 374 | for (var i = 0, len = value.length; i < len; i += 1) { |
360 | | - deepGet(value[i], remaining); |
| 375 | + deepGet(value[i], path, index + 1); |
361 | 376 | } |
362 | | - } else if (remaining) { |
| 377 | + } else if (path.length) { |
363 | 378 | // An object. Recurse further. |
364 | | - deepGet(value, remaining); |
| 379 | + deepGet(value, path, index + 1); |
365 | 380 | } |
366 | 381 | } |
367 | 382 | }; |
368 | 383 |
|
369 | | - deepGet(obj, path); |
| 384 | + deepGet(obj, path, 0); |
370 | 385 | return arr ? list : list[0]; |
371 | 386 | } |
372 | 387 |
|
|
479 | 494 | }, { |
480 | 495 | key: "setKeys", |
481 | 496 | value: function setKeys() { |
| 497 | + var _this = this; |
| 498 | + |
482 | 499 | var keys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; |
483 | 500 | this.keys = keys; |
| 501 | + this._keysMap = {}; |
| 502 | + keys.forEach(function (key, idx) { |
| 503 | + _this._keysMap[key.id] = idx; |
| 504 | + }); |
484 | 505 | } |
485 | 506 | }, { |
486 | 507 | key: "create", |
487 | 508 | value: function create() { |
488 | | - var _this = this; |
| 509 | + var _this2 = this; |
489 | 510 |
|
490 | 511 | if (this.isCreated || !this.docs.length) { |
491 | 512 | return; |
|
495 | 516 |
|
496 | 517 | if (isString(this.docs[0])) { |
497 | 518 | this.docs.forEach(function (doc, docIndex) { |
498 | | - _this._addString(doc, docIndex); |
| 519 | + _this2._addString(doc, docIndex); |
499 | 520 | }); |
500 | 521 | } else { |
501 | 522 | // List is Array<Object> |
502 | 523 | this.docs.forEach(function (doc, docIndex) { |
503 | | - _this._addObject(doc, docIndex); |
| 524 | + _this2._addObject(doc, docIndex); |
504 | 525 | }); |
505 | 526 | } |
506 | 527 |
|
|
528 | 549 | this.records[i].i -= 1; |
529 | 550 | } |
530 | 551 | } |
| 552 | + }, { |
| 553 | + key: "getValueForItemAtKeyId", |
| 554 | + value: function getValueForItemAtKeyId(item, keyId) { |
| 555 | + return item[this._keysMap[keyId]]; |
| 556 | + } |
531 | 557 | }, { |
532 | 558 | key: "size", |
533 | 559 | value: function size() { |
|
550 | 576 | }, { |
551 | 577 | key: "_addObject", |
552 | 578 | value: function _addObject(doc, docIndex) { |
553 | | - var _this2 = this; |
| 579 | + var _this3 = this; |
554 | 580 |
|
555 | 581 | var record = { |
556 | 582 | i: docIndex, |
557 | 583 | $: {} |
558 | 584 | }; // Iterate over every key (i.e, path), and fetch the value at that key |
559 | 585 |
|
560 | 586 | 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); |
562 | 589 |
|
563 | 590 | if (!isDefined(value)) { |
564 | 591 | return; |
|
585 | 612 | var subRecord = { |
586 | 613 | v: _value, |
587 | 614 | i: nestedArrIndex, |
588 | | - n: _this2.norm.get(_value) |
| 615 | + n: _this3.norm.get(_value) |
589 | 616 | }; |
590 | 617 | subRecords.push(subRecord); |
591 | 618 | } else if (isArray(_value)) { |
|
603 | 630 | } else if (!isBlank(value)) { |
604 | 631 | var subRecord = { |
605 | 632 | v: value, |
606 | | - n: _this2.norm.get(value) |
| 633 | + n: _this3.norm.get(value) |
607 | 634 | }; |
608 | 635 | record.$[keyIndex] = subRecord; |
609 | 636 | } |
|
630 | 657 | var myIndex = new FuseIndex({ |
631 | 658 | getFn: getFn |
632 | 659 | }); |
633 | | - var keyStore = new KeyStore(keys); |
634 | | - myIndex.setKeys(keyStore.keys()); |
| 660 | + myIndex.setKeys(keys.map(function (key) { |
| 661 | + return createKey(key); |
| 662 | + })); |
635 | 663 | myIndex.setSources(docs); |
636 | 664 | myIndex.create(); |
637 | 665 | return myIndex; |
|
672 | 700 | }; |
673 | 701 |
|
674 | 702 | if (match.key) { |
675 | | - obj.key = match.key; |
| 703 | + obj.key = match.key.src; |
676 | 704 | } |
677 | 705 |
|
678 | 706 | if (match.idx > -1) { |
|
1664 | 1692 | AND: '$and', |
1665 | 1693 | OR: '$or' |
1666 | 1694 | }; |
| 1695 | + var KeyType = { |
| 1696 | + PATH: '$path', |
| 1697 | + PATTERN: '$val' |
| 1698 | + }; |
1667 | 1699 |
|
1668 | 1700 | var isExpression = function isExpression(query) { |
1669 | 1701 | return !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]); |
1670 | 1702 | }; |
1671 | 1703 |
|
| 1704 | + var isPath = function isPath(query) { |
| 1705 | + return !!query[KeyType.PATH]; |
| 1706 | + }; |
| 1707 | + |
1672 | 1708 | var isLeaf = function isLeaf(query) { |
1673 | 1709 | return !isArray(query) && isObject(query) && !isExpression(query); |
1674 | 1710 | }; |
|
1688 | 1724 |
|
1689 | 1725 | var next = function next(query) { |
1690 | 1726 | var keys = Object.keys(query); |
| 1727 | + var isQueryPath = isPath(query); |
1691 | 1728 |
|
1692 | | - if (keys.length > 1 && !isExpression(query)) { |
| 1729 | + if (!isQueryPath && keys.length > 1 && !isExpression(query)) { |
1693 | 1730 | return next(convertToExplicit(query)); |
1694 | 1731 | } |
1695 | 1732 |
|
1696 | | - var key = keys[0]; |
1697 | | - |
1698 | 1733 | 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]; |
1700 | 1736 |
|
1701 | 1737 | if (!isString(pattern)) { |
1702 | 1738 | throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key)); |
1703 | 1739 | } |
1704 | 1740 |
|
1705 | 1741 | var obj = { |
1706 | | - key: key, |
| 1742 | + keyId: createKeyId(key), |
1707 | 1743 | pattern: pattern |
1708 | 1744 | }; |
1709 | 1745 |
|
|
1716 | 1752 |
|
1717 | 1753 | var node = { |
1718 | 1754 | children: [], |
1719 | | - operator: key |
| 1755 | + operator: keys[0] |
1720 | 1756 | }; |
1721 | 1757 | keys.forEach(function (key) { |
1722 | 1758 | var value = query[key]; |
|
1763 | 1799 | throw new Error(INCORRECT_INDEX_TYPE); |
1764 | 1800 | } |
1765 | 1801 |
|
1766 | | - this._myIndex = index || createIndex(this._keyStore.keys(), this._docs, { |
| 1802 | + this._myIndex = index || createIndex(this.options.keys, this._docs, { |
1767 | 1803 | getFn: this.options.getFn |
1768 | 1804 | }); |
1769 | 1805 | } |
|
1886 | 1922 | var _this = this; |
1887 | 1923 |
|
1888 | 1924 | 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; |
1892 | 1926 | var resultMap = {}; |
1893 | 1927 | var results = []; |
1894 | 1928 |
|
|
1921 | 1955 |
|
1922 | 1956 | return res; |
1923 | 1957 | } else { |
1924 | | - var key = node.key, |
| 1958 | + var keyId = node.keyId, |
1925 | 1959 | searcher = node.searcher; |
1926 | | - var value = item[keys.indexOf(key)]; |
| 1960 | + |
| 1961 | + var value = _this._myIndex.getValueForItemAtKeyId(item, keyId); |
| 1962 | + |
1927 | 1963 | return _this._findMatches({ |
1928 | | - key: key, |
| 1964 | + key: _this._keyStore.get(keyId), |
1929 | 1965 | value: value, |
1930 | 1966 | searcher: searcher |
1931 | 1967 | }); |
|
1968 | 2004 | var _this2 = this; |
1969 | 2005 |
|
1970 | 2006 | 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; |
1974 | 2010 | var results = []; // List is Array<Object> |
1975 | 2011 |
|
1976 | 2012 | records.forEach(function (_ref5) { |
|
2076 | 2112 | var key = _ref9.key, |
2077 | 2113 | norm = _ref9.norm, |
2078 | 2114 | score = _ref9.score; |
2079 | | - var weight = keyStore.get(key, 'weight'); |
| 2115 | + var weight = key ? key.weight : null; |
2080 | 2116 | totalScore *= Math.pow(score === 0 && weight ? Number.EPSILON : score, (weight || 1) * (ignoreFieldNorm ? 1 : norm)); |
2081 | 2117 | }); |
2082 | 2118 | result.score = totalScore; |
|
0 commit comments