diff options
| author | Geo Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2024-04-15 18:41:27 +0300 |
|---|---|---|
| committer | Geo Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2024-04-15 18:41:27 +0300 |
| commit | 3894db0824bbb0023bce8402f1c4f578504fb8ce (patch) | |
| tree | d74e86ea41fb83ede379429e7b9bc3e4408f96ba | |
| parent | b122279ece06a9381e805c6087f130b41616fe3d (diff) | |
| download | oseine-3894db0824bbb0023bce8402f1c4f578504fb8ce.tar.gz oseine-3894db0824bbb0023bce8402f1c4f578504fb8ce.tar.bz2 oseine-3894db0824bbb0023bce8402f1c4f578504fb8ce.zip | |
refactoring routes; added weighted exact and partial match routines
| -rw-r--r-- | app.js | 17 | ||||
| -rw-r--r-- | benchmark/match-str.js | 48 | ||||
| -rw-r--r-- | routes/dev.js (renamed from paths.js) | 72 | ||||
| -rw-r--r-- | routes/index.js | 26 | ||||
| -rw-r--r-- | routes/v1.js | 51 | ||||
| -rw-r--r-- | utils/match-util.js | 38 |
6 files changed, 171 insertions, 81 deletions
@@ -1,19 +1,18 @@ // app.js -const Koa = require('koa'); -const { koaBody } = require('koa-body'); +const Koa = require('koa'); +// const { koaBody } = require('koa-body'); require('dotenv').config(); +// define app const app = new Koa(); // middleware -app.use(koaBody()); - -// Require the routers -let paths = require('./paths.js'); +// app.use(koaBody()); -// use the routes -app.use(paths.routes()); +// Require routes +let _r = require('./routes'); +app.use(_r.routes()).use(_r.allowedMethods()); -// app.listen(3000); +// start server listening on APP_PORT app.listen(process.env.APP_PORT); diff --git a/benchmark/match-str.js b/benchmark/match-str.js index fa802c1..2114f41 100644 --- a/benchmark/match-str.js +++ b/benchmark/match-str.js @@ -2,6 +2,7 @@ var microtime = require('microtime'); const match = require('../utils/match-util.js'); const memory_usage = require('../utils/mem-usage.js'); +const kb = require('../utils/kb-util.js'); const products = require('../data/products.json'); @@ -25,27 +26,48 @@ function run(query) { } } -// sumple search implementation -function matchQuery(q) { +// sample search implementation +function matchQuery(query) { var result = []; + let q = kb.keyboardize(query); + for(let i = 0; i < products.length; i++) { + + let rate = 0; let found = false; - let similarity = 0; - products[i].kb.split(' ').forEach( w => { - let sim = match.resemblance(q, w, 2); - if (sim > 0.5) { - found = true; - similarity = (sim > similarity) ? sim : similarity; - } - }); + let x; + let src = products[i].kb.split(' '); // (array) source of product (key-)words + if ((x = match.weighted_exact(q, src)) > 0) { + // console.log(products[i].kb, x); + rate = 5.0 + x; + found = true; + } + else if ((x = match.weighted_partial(q, src)) > 0) { + rate = 3.0 + x; + found = true; + } + else { + let similarity = 0; + src.forEach( w => { + let sim = match.resemblance(q, w, 2); + if (sim > 0.6) { + found = true; + similarity = (sim > similarity) ? sim : similarity; + } + }); + if (found) { + rate = 2 * similarity; + } + } + if (found) { - products[i].similarity = similarity; + products[i].rate = rate; result.push(products[i]); - } + } } - return result + return result.sort((a,b) => b.rate - a.rate).slice(0, 48);; } @@ -4,20 +4,20 @@ */ const Router = require('koa-router'); -const urler = require('./utils/url-util'); +const urler = require('../utils/url-util.js'); -const data = require('./pieces/prepare-streams'); +const data = require('../pieces/prepare-streams.js'); -const bench = require('./benchmark/find.js'); -const matchStr = require('./benchmark/match-str.js'); +const bench = require('../benchmark/find.js'); +const matchStr = require('../benchmark/match-str.js'); // Prefix all routes with: /items -const router = new Router({ - // prefix: '/items' -}); +const router = new Router(); + +// Routes /* simple route example @@ -27,9 +27,7 @@ const router = new Router({ { id: 102, iname: 'Apple iPod', price: 'US $219.99'}, { id: 103, iname: 'Prince Phantom 97P Tennnis Racket', price: 'US $50.00'}, ]; - - // Routes - + router.get('/items', (ctx, next) => { ctx.body = items; next(); @@ -56,56 +54,15 @@ const router = new Router({ // https://stackoverflow.com/questions/66634123/how-to-add-individual-timeout-value-per-specific-route-using-node-js -// Routes - -router.get('/', (ctx, next) => { - ctx.body = { - success: true, - title: 'oseine', - description: 'oseine search engine is not elastic', - message: 'where are you now?' - } - next(); -}) - -router.get('/search', (ctx, next) => { - ctx.body = []; - next(); -}); - -router.get('/search/:title', (ctx, next) => { - // console.log(ctx); - const kb = require('./utils/kb-util.js'); - let words = kb.keyboardize(kb.clean(ctx.params.title)).split(' '); - ctx.body = { - params: ctx.params, - results: words, - nxt: next - }; - next(); -}); - - - -/** other routes - * ///////////////////////////////////////////////////////////////////////////// - * + /suggest/<some search string> - * + /prepare (products, keywords, linked-terms etc) - * + /stats - */ - - - // TEST routes //////////////////////////////////////////////////////////////////////////////// -router.get('/test', (ctx, next) => { // easy test route +router.get('/test', (ctx) => { // easy test route // test anything ... ctx.body = { params: urler.struct(ctx.request, ctx.url), ctx: ctx } - next(); }); -router.get('/test/do-data', (ctx, next) => { // easy test route +router.get('/test/do-data', (ctx) => { // easy test route // test anything ... // data.create( // 'products', @@ -115,7 +72,6 @@ router.get('/test/do-data', (ctx, next) => { // easy test route 'https://storage.googleapis.com/pythia-files/uploads/json/emarket-products.json' ); ctx.body = { success: true, operation: 'create new data' }; - next(); }); // benchmark routes; @@ -128,17 +84,17 @@ router.get('/test/do-data', (ctx, next) => { // easy test route /// next(); /// }); -router.get('/bench/find', (ctx, next) => { // easy test route +router.get('/bench/find', (ctx) => { // easy test route // test anything ... ctx.body = bench.compare(); - next(); + // next(); }); -router.get('/bench/match/:title', (ctx, next) => { // easy test route +router.get('/bench/match/:title', (ctx) => { // easy test route // test anything ... [ query = 'solokata' ] // ctx.body = bench.compare(); ctx.body = matchStr.run(ctx.params.title); - next(); + // next(); }); diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..e3d6230 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,26 @@ +/** + * routes (index) + */ +const Router = require('koa-router'); + +const router = new Router(); + +// Require grouped routes + +let v1 = require('./v1.js'); +router.use(v1.routes()); + +let dev_paths = require('./dev.js'); +router.use(dev_paths.routes()); + +// define default route +router.get('/', (ctx) => { + ctx.body = { + success: true, + title: 'oseine', + description: 'oseine search engine is not elastic', + message: 'where are you now?' + } +}) + +module.exports = router; diff --git a/routes/v1.js b/routes/v1.js new file mode 100644 index 0000000..859f7b0 --- /dev/null +++ b/routes/v1.js @@ -0,0 +1,51 @@ +/** + * api v1 routes + */ + +const Router = require('koa-router'); + + +// Prefix all routes with: /items +const router = new Router({ + prefix: '/v1' +}); + + + +// Routes + + + +router.get('/search', (ctx) => { + ctx.body = { success: true, results: [] }; +}); + +router.get('/search/:title', (ctx) => { + let result = [ + { id: 10, w: 'Ένα Προϊόν' }, + { id: 15, w: 'Άλλο Προϊόν' }, + { id: 20, w: 'Προϊόν 3' }, + { id: 25, w: 'Προϊόν 4' } + ] + // console.log(ctx); + /// const kb = require('./utils/kb-util.js'); + /// let words = kb.keyboardize(kb.clean(ctx.params.title)).split(' '); + /// ctx.body = { + /// params: ctx.params, + /// results: words, + /// nxt: next + /// }; + ctx.body = result; +}); + + +/** TODO: ?? other routes ?? + * ///////////////////////////////////////////////////////////////////////////// + * + /suggest/<some search string> + * + /prepare (products, keywords, linked-terms etc) + * + /stats + */ + + +// export routes +module.exports = router; diff --git a/utils/match-util.js b/utils/match-util.js index a13fddb..b6b9fc0 100644 --- a/utils/match-util.js +++ b/utils/match-util.js @@ -64,7 +64,6 @@ const resemblance = (a, b, n) => { /** is_exact_match - * * check if a searching string -> query (string/latin in kb-format) * matches exactly an item of the array of synonyms -> chkArr (array of utf-8/strings) * @@ -84,9 +83,46 @@ function partial( query, chkArr ) { return found; } +/** is exact match + weight rating + * @returns {float} weight rates depth of array when a match is found + */ +function weighted_exact( query, chkArr ) { + let weight = 0; // closer to left/begin rating + let len = chkArr.length; + for(let i = 0; i < len ; i++) { + if (chkArr[i] == query) { + // rating weights array depth + weight = (len - i + 1.0) / len; + // console.log(i, weight, query); + break; + } + } + return weight; +} + + +/** is partial match + weight rating + * @returns {float} weight rates both match position and depth of match + */ +function weighted_partial( query, chkArr ) { + let rate = 0; + let weight = 0; + let len = chkArr.length; + for(let i = 0; i < len ; i++) { + let chk = chkArr[i].indexOf(query) + if (chk != -1) { + rate = (len -i +1.0) / (len + 2.0 * chk); + weight = rate > weight ? rate : weight; + } + } + return weight; +} + module.exports = { exact, partial, + weighted_exact, + weighted_partial, similarity, resemblance } |
