Skip to content

Commit 51a5a71

Browse files
committed
alustava typesense-vertailuskripti
1 parent c65df5e commit 51a5a71

File tree

2 files changed

+283
-0
lines changed

2 files changed

+283
-0
lines changed

backend/scripts/compareSearch.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#!/usr/bin/env node
2+
/*
3+
Compare search results between two Finlex services.
4+
Usage:
5+
node scripts/compareSearch.js --q tupakka --language fin
6+
node scripts/compareSearch.js --q tupakka --language fin --prod https://... --staging https://...
7+
node scripts/compareSearch.js --file words.txt --language fin
8+
*/
9+
10+
import axios from 'axios';
11+
import { readFileSync } from 'fs';
12+
13+
function parseArgs() {
14+
const args = process.argv.slice(2);
15+
const out = { q: null, file: null, language: 'fin', prod: 'https://finlex.ext.ocp-prod-0.k8s.it.helsinki.fi', staging: 'https://finlex-lukija-ohtuprojekti-staging.ext.ocp-prod-0.k8s.it.helsinki.fi' };
16+
for (let i = 0; i < args.length; i++) {
17+
const a = args[i];
18+
if (a === '--q') out.q = args[++i];
19+
else if (a === '--file') out.file = args[++i];
20+
else if (a === '--language') out.language = args[++i];
21+
else if (a === '--prod') out.prod = args[++i];
22+
else if (a === '--staging') out.staging = args[++i];
23+
}
24+
if (!out.q && !out.file) {
25+
console.error('Missing --q query parameter or --file path');
26+
process.exit(1);
27+
}
28+
return out;
29+
}
30+
31+
function buildUrl(base, q, language) {
32+
const params = new URLSearchParams({ q, language });
33+
return `${base}/api/statute/search?${params.toString()}`;
34+
}
35+
36+
function asArray(data) {
37+
if (Array.isArray(data)) return data;
38+
if (data && Array.isArray(data.content)) return data.content; // Finlex API wraps in {type, content}
39+
if (data && Array.isArray(data.results)) return data.results; // fallback
40+
return [];
41+
}
42+
43+
function indexById(list) {
44+
const map = new Map();
45+
for (const item of list) {
46+
// API returns docYear, docNumber, docTitle (not year, number, title)
47+
const key = item.id || `${item.docYear || ''}:${item.docNumber || ''}:${item.docTitle || ''}`;
48+
map.set(key, item);
49+
}
50+
return map;
51+
}
52+
53+
function diffLists(aList, bList) {
54+
const aMap = indexById(aList);
55+
const bMap = indexById(bList);
56+
const onlyA = [];
57+
const onlyB = [];
58+
59+
for (const [id, item] of aMap.entries()) {
60+
if (!bMap.has(id)) onlyA.push(item);
61+
}
62+
for (const [id, item] of bMap.entries()) {
63+
if (!aMap.has(id)) onlyB.push(item);
64+
}
65+
return { onlyA, onlyB };
66+
}
67+
68+
async function compareQuery(q, language, prod, staging) {
69+
const prodUrl = buildUrl(prod, q, language);
70+
const stagingUrl = buildUrl(staging, q, language);
71+
72+
try {
73+
const [prodResp, stagingResp] = await Promise.all([
74+
axios.get(prodUrl, { headers: { Accept: 'application/json' } }),
75+
axios.get(stagingUrl, { headers: { Accept: 'application/json' } }),
76+
]);
77+
78+
const prodList = asArray(prodResp.data);
79+
const stagingList = asArray(stagingResp.data);
80+
81+
const { onlyA: onlyProd, onlyB: onlyStaging } = diffLists(prodList, stagingList);
82+
83+
return {
84+
q,
85+
prodCount: prodList.length,
86+
stagingCount: stagingList.length,
87+
onlyProd,
88+
onlyStaging,
89+
match: onlyProd.length === 0 && onlyStaging.length === 0
90+
};
91+
} catch (err) {
92+
return {
93+
q,
94+
error: err.response ? `${err.response.status} ${err.config?.url}` : err.message
95+
};
96+
}
97+
}
98+
99+
async function main() {
100+
const { q, file, language, prod, staging } = parseArgs();
101+
102+
let queries = [];
103+
if (file) {
104+
const content = readFileSync(file, 'utf-8');
105+
queries = content.split('\n').map(line => line.trim()).filter(line => line && !line.startsWith('#'));
106+
} else {
107+
queries = [q];
108+
}
109+
110+
console.log(`Testing ${queries.length} queries against prod and staging (language=${language})\n`);
111+
112+
const results = [];
113+
for (const query of queries) {
114+
process.stdout.write(`Testing "${query}"... `);
115+
const result = await compareQuery(query, language, prod, staging);
116+
results.push(result);
117+
118+
if (result.error) {
119+
console.log(`ERROR: ${result.error}`);
120+
} else if (result.match) {
121+
console.log(`✓ Match (prod: ${result.prodCount}, staging: ${result.stagingCount})`);
122+
} else {
123+
console.log(`✗ Diff (prod: ${result.prodCount}, staging: ${result.stagingCount}, only-prod: ${result.onlyProd.length}, only-staging: ${result.onlyStaging.length})`);
124+
}
125+
}
126+
127+
console.log('\n=== Summary ===');
128+
const matches = results.filter(r => !r.error && r.match).length;
129+
const diffs = results.filter(r => !r.error && !r.match).length;
130+
const errors = results.filter(r => r.error).length;
131+
console.log(`Total: ${results.length}, Matches: ${matches}, Diffs: ${diffs}, Errors: ${errors}`);
132+
133+
const problemResults = results.filter(r => r.error || !r.match);
134+
if (problemResults.length > 0) {
135+
console.log('\n=== Details for non-matching queries ===');
136+
for (const result of problemResults) {
137+
if (result.error) {
138+
console.log(`\n"${result.q}": ERROR - ${result.error}`);
139+
} else {
140+
console.log(`\n"${result.q}": prod=${result.prodCount}, staging=${result.stagingCount}`);
141+
if (result.onlyProd.length > 0) {
142+
console.log(` Only in prod (${result.onlyProd.length}):`, result.onlyProd.map(i => `${i.docYear}/${i.docNumber}`).join(', '));
143+
}
144+
if (result.onlyStaging.length > 0) {
145+
console.log(` Only in staging (${result.onlyStaging.length}):`, result.onlyStaging.map(i => `${i.docYear}/${i.docNumber}`).join(', '));
146+
}
147+
}
148+
}
149+
}
150+
}
151+
152+
main();

backend/scripts/queries.txt

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
laki
2+
oikeus
3+
oikeudellinen
4+
säännös
5+
asetus
6+
lakikokoelma
7+
pykälä
8+
momentti
9+
kohta
10+
artikla
11+
lauseke
12+
liite
13+
muutos
14+
kumota
15+
voimaantulo
16+
soveltaa
17+
noudattaa
18+
viranomainen
19+
hallinto
20+
tuomioistuin
21+
oikeusaste
22+
tuomari
23+
lautamies
24+
käräjäoikeus
25+
hovioikeus
26+
korkein
27+
käsittely
28+
istunto
29+
oikeudenkäynti
30+
valitus
31+
hakemus
32+
päätös
33+
tuomio
34+
määräys
35+
ratkaisu
36+
asianomainen
37+
asianosainen
38+
hakija
39+
vastaaja
40+
kantaja
41+
syyttäjä
42+
avustaja
43+
asianajaja
44+
edustaja
45+
valtuutettu
46+
oikeuskelpoisuus
47+
toimivalta
48+
vastuu
49+
velvollisuus
50+
oikeusvastuu
51+
korvausvastuu
52+
seuraamus
53+
sopimus
54+
sopimusehto
55+
suostumus
56+
tarjous
57+
hyväksyminen
58+
vastike
59+
ehto
60+
velvoite
61+
täytäntöönpano
62+
irtisanominen
63+
purku
64+
vahingonkorvaus
65+
hyvitys
66+
omaisuus
67+
omistusoikeus
68+
hallinta
69+
luovutus
70+
vuokra
71+
vuokrasopimus
72+
pantti
73+
vakuus
74+
kiinnitys
75+
kauppa
76+
myynti
77+
ostos
78+
liiketoimi
79+
rikos
80+
rikosoikeus
81+
teko
82+
tahallisuus
83+
huolimattomuus
84+
petos
85+
varkaus
86+
pahoinpitely
87+
rangaistus
88+
sakko
89+
vankeus
90+
tuomitseminen
91+
hallintolaki
92+
virasto
93+
lupa
94+
ilmoitus
95+
rekisteri
96+
julkinen
97+
salassapito
98+
tietosuoja
99+
asiakirja
100+
todiste
101+
todistelu
102+
todistaja
103+
lausunto
104+
selvitys
105+
näyttö
106+
todistustaakka
107+
menettely
108+
prosessi
109+
määräaika
110+
viivästys
111+
kuuleminen
112+
täytäntöönpano
113+
täytäntöönpide
114+
oikaisu
115+
muutoksenhaku
116+
kumoaminen
117+
pätevyys
118+
tulkinta
119+
merkitys
120+
tarkoitus
121+
soveltamisala
122+
määritelmä
123+
epäselvyys
124+
yhteensopivuus
125+
kansainvälinen
126+
sopimusvaltio
127+
toimivaltaisuus
128+
tuomiovalta
129+
välimiesmenettely
130+
sovittelu
131+

0 commit comments

Comments
 (0)