on master help sign in
Merge pull request #1573 from urbit/mp/new-algo

search: use Levenshtein distance algorithm

commit6f8e66fc110835bcfe3ad1cce7593db445453e8d authormatildepark <matilde.park@urbit.org> dateMon 20 Jun 2022, 12:15 (4 years ago) parentd012421085488f
4 files changed+74−37
components/Search.js+4−1 package-lock.json+64−34 package.json+1 pages/api/search.js+5−2
components/Search.js+4−1
@@ -5,6 +5,7 @@ import debounce from "lodash.debounce";
55import Downshift from "downshift";
66import ob from "urbit-ob";
77import Sigil from "../components/Sigil";
8+import levenSort from "leven-sort";
89
910class Search extends Component {
1011 constructor(props) {
@@ -24,11 +25,12 @@ class Search extends Component {
2425 }
2526
2627 glossarySearch(query) {
27− return glossary.filter((entry) => {
28+ const entries = glossary.filter((entry) => {
2829 return (
2930 entry.name.includes(query.toLowerCase()) || entry.symbol.includes(query)
3031 );
3132 });
33+ return levenSort(entries, query, ["symbol"]);
3234 }
3335
3436 patpSearch(query) {
@@ -57,6 +59,7 @@ class Search extends Component {
5759 fetch(this.searchEndpoint(query))
5860 .then((res) => res.json())
5961 .then((res) => {
62+ console.log(res);
6063 // Wrap results in an object which will tell React what component to use to render results.
6164 const results = res.results.map((item) => ({
6265 type: "RESULT",
package-lock.json+64−34
@@ -20,6 +20,7 @@
2020 "feed": "^4.2.2",
2121 "foundation-design-system": "github:urbit/foundation-design-system",
2222 "gray-matter": "^4.0.3",
23+ "leven-sort": "^3.0.0",
2324 "lodash.debounce": "^4.0.8",
2425 "lodash.omit": "^4.5.0",
2526 "luxon": "^2.0.2",
@@ -76,9 +77,9 @@
7677 "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
7778 },
7879 "node_modules/@markdoc/markdoc": {
79− "version": "0.1.2",
80− "resolved": "https://registry.npmjs.org/@markdoc/markdoc/-/markdoc-0.1.2.tgz",
81− "integrity": "sha512-3p+JTC1A0eqBdrl2UOIRoy+FLKtG1mh81R3Zzdm7FJiQIMt2mJmqmVQNDf3Md62G9rTtbj0ZuxlEattMbaslbw==",
80+ "version": "0.1.3",
81+ "resolved": "https://registry.npmjs.org/@markdoc/markdoc/-/markdoc-0.1.3.tgz",
82+ "integrity": "sha512-4n2cobUSeOob+237wZhpNiOEHCSfOydlQnKHTFdRY6ug/DupXGaxkkkszJYQxRftiMs8jmb10XvVO1svEYD43Q==",
8283 "engines": {
8384 "node": ">=14.7.0"
8485 }
@@ -589,9 +590,9 @@
589590 }
590591 },
591592 "node_modules/caniuse-lite": {
592− "version": "1.0.30001355",
593− "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001355.tgz",
594− "integrity": "sha512-Sd6pjJHF27LzCB7pT7qs+kuX2ndurzCzkpJl6Qct7LPSZ9jn0bkOA8mdgMgmqnQAWLVOOGjLpc+66V57eLtb1g==",
593+ "version": "1.0.30001357",
594+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001357.tgz",
595+ "integrity": "sha512-b+KbWHdHePp+ZpNj+RDHFChZmuN+J5EvuQUlee9jOQIUAdhv9uvAZeEtUeLAknXbkiu1uxjQ9NLp1ie894CuWg==",
595596 "funding": [
596597 {
597598 "type": "opencollective",
@@ -687,9 +688,9 @@
687688 "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
688689 },
689690 "node_modules/core-js": {
690− "version": "3.23.1",
691− "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.1.tgz",
692− "integrity": "sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w==",
691+ "version": "3.23.2",
692+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.2.tgz",
693+ "integrity": "sha512-ELJOWxNrJfOH/WK4VJ3Qd+fOqZuOuDNDJz0xG6Bt4mGg2eO/UT9CljCrbqDGovjLKUrGajEEBcoTOc0w+yBYeQ==",
693694 "hasInstallScript": true,
694695 "funding": {
695696 "type": "opencollective",
@@ -859,9 +860,9 @@
859860 }
860861 },
861862 "node_modules/electron-to-chromium": {
862− "version": "1.4.158",
863− "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.158.tgz",
864− "integrity": "sha512-gppO3/+Y6sP432HtvwvuU8S+YYYLH4PmAYvQwqUtt9HDOmEsBwQfLnK9T8+1NIKwAS1BEygIjTaATC4H5EzvxQ=="
863+ "version": "1.4.161",
864+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.161.tgz",
865+ "integrity": "sha512-sTjBRhqh6wFodzZtc5Iu8/R95OkwaPNn7tj/TaDU5nu/5EFiQDtADGAXdR4tJcTEHlYfJpHqigzJqHvPgehP8A=="
865866 },
866867 "node_modules/end-of-stream": {
867868 "version": "1.4.4",
@@ -1107,7 +1108,7 @@
11071108 },
11081109 "node_modules/foundation-design-system": {
11091110 "version": "0.0.0",
1110− "resolved": "git+ssh://git@github.com/urbit/foundation-design-system.git#ba69c83265b7cca109217fa6a2b2539a57087f4a",
1111+ "resolved": "git+ssh://git@github.com/urbit/foundation-design-system.git#2d3235b586507cb3bfdb99880e517ddaaa77ede0",
11111112 "license": "MIT",
11121113 "dependencies": {
11131114 "@babel/polyfill": "^7.12.1",
@@ -1583,6 +1584,22 @@
15831584 "graceful-fs": "^4.1.11"
15841585 }
15851586 },
1587+ "node_modules/leven": {
1588+ "version": "3.1.0",
1589+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
1590+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
1591+ "engines": {
1592+ "node": ">=6"
1593+ }
1594+ },
1595+ "node_modules/leven-sort": {
1596+ "version": "3.0.0",
1597+ "resolved": "https://registry.npmjs.org/leven-sort/-/leven-sort-3.0.0.tgz",
1598+ "integrity": "sha512-dw+6CDkFAbmXiAv/bU2IQKEJzgdXUYnc2Z4FipY9gOt+tdUUiP1R1Jn8S05aORllj5NLcKyx6zwIz+M3ygCohA==",
1599+ "dependencies": {
1600+ "leven": "^3.1.0"
1601+ }
1602+ },
15861603 "node_modules/lilconfig": {
15871604 "version": "2.0.5",
15881605 "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
@@ -2472,11 +2489,11 @@
24722489 }
24732490 },
24742491 "node_modules/resolve": {
2475− "version": "1.22.0",
2476− "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
2477− "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
2492+ "version": "1.22.1",
2493+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
2494+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
24782495 "dependencies": {
2479− "is-core-module": "^2.8.1",
2496+ "is-core-module": "^2.9.0",
24802497 "path-parse": "^1.0.7",
24812498 "supports-preserve-symlinks-flag": "^1.0.0"
24822499 },
@@ -2932,9 +2949,9 @@
29322949 "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg=="
29332950 },
29342951 "@markdoc/markdoc": {
2935− "version": "0.1.2",
2936− "resolved": "https://registry.npmjs.org/@markdoc/markdoc/-/markdoc-0.1.2.tgz",
2937− "integrity": "sha512-3p+JTC1A0eqBdrl2UOIRoy+FLKtG1mh81R3Zzdm7FJiQIMt2mJmqmVQNDf3Md62G9rTtbj0ZuxlEattMbaslbw=="
2952+ "version": "0.1.3",
2953+ "resolved": "https://registry.npmjs.org/@markdoc/markdoc/-/markdoc-0.1.3.tgz",
2954+ "integrity": "sha512-4n2cobUSeOob+237wZhpNiOEHCSfOydlQnKHTFdRY6ug/DupXGaxkkkszJYQxRftiMs8jmb10XvVO1svEYD43Q=="
29382955 },
29392956 "@next/env": {
29402957 "version": "12.1.6",
@@ -3222,9 +3239,9 @@
32223239 "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
32233240 },
32243241 "caniuse-lite": {
3225− "version": "1.0.30001355",
3226− "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001355.tgz",
3227− "integrity": "sha512-Sd6pjJHF27LzCB7pT7qs+kuX2ndurzCzkpJl6Qct7LPSZ9jn0bkOA8mdgMgmqnQAWLVOOGjLpc+66V57eLtb1g=="
3242+ "version": "1.0.30001357",
3243+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001357.tgz",
3244+ "integrity": "sha512-b+KbWHdHePp+ZpNj+RDHFChZmuN+J5EvuQUlee9jOQIUAdhv9uvAZeEtUeLAknXbkiu1uxjQ9NLp1ie894CuWg=="
32283245 },
32293246 "chalk": {
32303247 "version": "2.4.2",
@@ -3295,9 +3312,9 @@
32953312 "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
32963313 },
32973314 "core-js": {
3298− "version": "3.23.1",
3299− "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.1.tgz",
3300− "integrity": "sha512-wfMYHWi1WQjpgZNC9kAlN4ut04TM9fUTdi7CqIoTVM7yaiOUQTklOzfb+oWH3r9edQcT3F887swuVmxrV+CC8w=="
3315+ "version": "3.23.2",
3316+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.23.2.tgz",
3317+ "integrity": "sha512-ELJOWxNrJfOH/WK4VJ3Qd+fOqZuOuDNDJz0xG6Bt4mGg2eO/UT9CljCrbqDGovjLKUrGajEEBcoTOc0w+yBYeQ=="
33013318 },
33023319 "cross-spawn": {
33033320 "version": "6.0.5",
@@ -3418,9 +3435,9 @@
34183435 }
34193436 },
34203437 "electron-to-chromium": {
3421− "version": "1.4.158",
3422− "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.158.tgz",
3423− "integrity": "sha512-gppO3/+Y6sP432HtvwvuU8S+YYYLH4PmAYvQwqUtt9HDOmEsBwQfLnK9T8+1NIKwAS1BEygIjTaATC4H5EzvxQ=="
3438+ "version": "1.4.161",
3439+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.161.tgz",
3440+ "integrity": "sha512-sTjBRhqh6wFodzZtc5Iu8/R95OkwaPNn7tj/TaDU5nu/5EFiQDtADGAXdR4tJcTEHlYfJpHqigzJqHvPgehP8A=="
34243441 },
34253442 "end-of-stream": {
34263443 "version": "1.4.4",
@@ -3594,7 +3611,7 @@
35943611 "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
35953612 },
35963613 "foundation-design-system": {
3597− "version": "git+ssh://git@github.com/urbit/foundation-design-system.git#ba69c83265b7cca109217fa6a2b2539a57087f4a",
3614+ "version": "git+ssh://git@github.com/urbit/foundation-design-system.git#2d3235b586507cb3bfdb99880e517ddaaa77ede0",
35983615 "from": "foundation-design-system@github:urbit/foundation-design-system",
35993616 "requires": {
36003617 "@babel/polyfill": "^7.12.1",
@@ -3931,6 +3948,19 @@
39313948 "graceful-fs": "^4.1.11"
39323949 }
39333950 },
3951+ "leven": {
3952+ "version": "3.1.0",
3953+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
3954+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
3955+ },
3956+ "leven-sort": {
3957+ "version": "3.0.0",
3958+ "resolved": "https://registry.npmjs.org/leven-sort/-/leven-sort-3.0.0.tgz",
3959+ "integrity": "sha512-dw+6CDkFAbmXiAv/bU2IQKEJzgdXUYnc2Z4FipY9gOt+tdUUiP1R1Jn8S05aORllj5NLcKyx6zwIz+M3ygCohA==",
3960+ "requires": {
3961+ "leven": "^3.1.0"
3962+ }
3963+ },
39343964 "lilconfig": {
39353965 "version": "2.0.5",
39363966 "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
@@ -4530,11 +4560,11 @@
45304560 "integrity": "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg=="
45314561 },
45324562 "resolve": {
4533− "version": "1.22.0",
4534− "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
4535− "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
4563+ "version": "1.22.1",
4564+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
4565+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
45364566 "requires": {
4537− "is-core-module": "^2.8.1",
4567+ "is-core-module": "^2.9.0",
45384568 "path-parse": "^1.0.7",
45394569 "supports-preserve-symlinks-flag": "^1.0.0"
45404570 }
package.json+1
@@ -29,6 +29,7 @@
2929 "feed": "^4.2.2",
3030 "foundation-design-system": "github:urbit/foundation-design-system",
3131 "gray-matter": "^4.0.3",
32+ "leven-sort": "^3.0.0",
3233 "lodash.debounce": "^4.0.8",
3334 "lodash.omit": "^4.5.0",
3435 "luxon": "^2.0.2",
pages/api/search.js+5−2
@@ -1,12 +1,15 @@
11import { index } from "../../cache/data";
2+const levenSort = require("leven-sort");
23
34export default (req, res) => {
45 const results = index.filter(
56 (e) =>
67 e.title?.toLowerCase().includes(req.query.q.toLowerCase()) ||
7− e?.slug.includes(req.query.q.toLowerCase())
8+ e?.slug.includes(req.query.q.toLowerCase()) ||
9+ e?.parent.toLowerCase().includes(req.query.q.toLowerCase())
810 );
11+ const sorted = levenSort(results, req.q, ["title", "slug", "parent"]);
912 res.statusCode = 200;
1013 res.setHeader("Content-Type", "application/json");
11− res.end(JSON.stringify({ results }));
14+ res.end(JSON.stringify({ results: sorted }));
1215};