summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeo Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2024-04-15 18:41:27 +0300
committerGeo Halkiadakis <gchalkiadakis@sklavenitis.co.gr>2024-04-15 18:41:27 +0300
commit3894db0824bbb0023bce8402f1c4f578504fb8ce (patch)
treed74e86ea41fb83ede379429e7b9bc3e4408f96ba
parentb122279ece06a9381e805c6087f130b41616fe3d (diff)
downloadoseine-3894db0824bbb0023bce8402f1c4f578504fb8ce.tar.gz
oseine-3894db0824bbb0023bce8402f1c4f578504fb8ce.tar.bz2
oseine-3894db0824bbb0023bce8402f1c4f578504fb8ce.zip
refactoring routes; added weighted exact and partial match routines
-rw-r--r--app.js17
-rw-r--r--benchmark/match-str.js48
-rw-r--r--routes/dev.js (renamed from paths.js)72
-rw-r--r--routes/index.js26
-rw-r--r--routes/v1.js51
-rw-r--r--utils/match-util.js38
6 files changed, 171 insertions, 81 deletions
diff --git a/app.js b/app.js
index aa79f62..c0392e6 100644
--- a/app.js
+++ b/app.js
@@ -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);;
}
diff --git a/paths.js b/routes/dev.js
index 6e5fbef..3f142d0 100644
--- a/paths.js
+++ b/routes/dev.js
@@ -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
}