on master help sign in
search: use Levenshtein distance algorithm

Fixes #1528

commit17bc14a3cd6f2ab3dbebd4039eb8987006689ef9 authorMatilde Park <matilde.park@urbit.org> dateWed 15 Jun 2022, 15:03 (4 years ago) parentabf1b49
4 files changed+40−3
components/Search.js+4−1 package-lock.json+30 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+30
@@ -24,6 +24,7 @@
2424 "gray-matter": "^4.0.3",
2525 "html-entities": "^2.3.2",
2626 "html-react-parser": "^1.4.14",
27+ "leven-sort": "^3.0.0",
2728 "lodash.debounce": "^4.0.8",
2829 "lodash.omit": "^4.5.0",
2930 "luxon": "^2.0.2",
@@ -1776,6 +1777,22 @@
17761777 "graceful-fs": "^4.1.11"
17771778 }
17781779 },
1780+ "node_modules/leven": {
1781+ "version": "3.1.0",
1782+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
1783+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
1784+ "engines": {
1785+ "node": ">=6"
1786+ }
1787+ },
1788+ "node_modules/leven-sort": {
1789+ "version": "3.0.0",
1790+ "resolved": "https://registry.npmjs.org/leven-sort/-/leven-sort-3.0.0.tgz",
1791+ "integrity": "sha512-dw+6CDkFAbmXiAv/bU2IQKEJzgdXUYnc2Z4FipY9gOt+tdUUiP1R1Jn8S05aORllj5NLcKyx6zwIz+M3ygCohA==",
1792+ "dependencies": {
1793+ "leven": "^3.1.0"
1794+ }
1795+ },
17791796 "node_modules/lilconfig": {
17801797 "version": "2.0.5",
17811798 "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
@@ -4593,6 +4610,19 @@
45934610 "graceful-fs": "^4.1.11"
45944611 }
45954612 },
4613+ "leven": {
4614+ "version": "3.1.0",
4615+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
4616+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="
4617+ },
4618+ "leven-sort": {
4619+ "version": "3.0.0",
4620+ "resolved": "https://registry.npmjs.org/leven-sort/-/leven-sort-3.0.0.tgz",
4621+ "integrity": "sha512-dw+6CDkFAbmXiAv/bU2IQKEJzgdXUYnc2Z4FipY9gOt+tdUUiP1R1Jn8S05aORllj5NLcKyx6zwIz+M3ygCohA==",
4622+ "requires": {
4623+ "leven": "^3.1.0"
4624+ }
4625+ },
45964626 "lilconfig": {
45974627 "version": "2.0.5",
45984628 "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz",
package.json+1
@@ -33,6 +33,7 @@
3333 "gray-matter": "^4.0.3",
3434 "html-entities": "^2.3.2",
3535 "html-react-parser": "^1.4.14",
36+ "leven-sort": "^3.0.0",
3637 "lodash.debounce": "^4.0.8",
3738 "lodash.omit": "^4.5.0",
3839 "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};