Adressprüfung Algorithmus & Onepager
Budget: €30 – €250 EUR
Ich plane einen schlanken One-Pager-Seite zur Adressprüfung mit Adressprüfungsalgorythmus, über den meine Kunden eigene Adresslisten hochladen, prüfen und anschließend – nach den ersten 30 kostenlosen Datensätzen – pro validiertem Eintrag bezahlen können.
Kernpunkte des Auftrags
1. Upload-Strecke
• Akzeptierte Formate: CSV, reine Textdateien oder Excel, typischer Umfang 1 000 – 5 000 Zeilen pro Datei. (können aber auch mehr sein) manuelle Möglichkeit zur Dateiprüfung sollte gegeben sein, z.B. bei Dateien mit mehreren Millionen Datensätzen
• Fortschrittsanzeige während des Uploads und der Prüfung
• festgelegter Datenaufbau sollte vorgegeben werden. Eine externe ID in der Datei sollte möglich sein.
2. Prüf-Algorithmus
• Postleitzahl -Überprüfung
• Straßenname -Überprüfung
• Ortsname-Validierung
• Hausnummerncheck (wenn eine Hausnummer vorhanden ist)
Die Routine soll pro Datensatz ein eindeutiges Prüfergebnis (ok / Fehlercode) liefern und idealerweise ein korrigiertes Feld ausgeben, falls klar erkannt.
3. Abrechnung & Payment
• Die ersten 30 Datensätze bleiben kostenfrei.
• Danach automatische Preisberechnung anhand der Anzahl geprüfter Einträge.
• Zahlung via PayPal (Einmalzahlung, keine Abo-Lösung).
4. Ergebnis-Bereitstellung
• Download einer geprüften Datei im Ursprungsformat, ergänzt um Spalten für Status und eventuelle Korrekturvorschläge.
• Kurzer PDF-Report mit Zusammenfassung (Anzahl geprüft, Fehlerverteilung).
5. Administration & Sicherheit
• Einfaches Backend oder Konfig-Datei, um Preise oder Freikontingent anzupassen.
• DSGVO-konforme Verarbeitung: verschlüsselte Übertragung, automatische Löschung der Dateien nach Abschluss.
Lieferumfang
– Voll funktionsfähiger One-Pager (HTML/CSS/JS oder Framework Ihrer Wahl) inkl. responsivem Design.
– Server-Side Logik für Upload, Prüfung und Payment
– Quellcode, Installationshinweise und kurze technische Dokumentation.
- Inklusive lauffähiger Installation auf einem Server (Windows)
Ich freue mich auf Vorschläge, wie Sie das Regelwerk effizient abbilden und die Zahlung reibungslos integrieren können. Bitte nennen Sie relevante Referenzen oder Libraries, die Sie einsetzen möchten.
Details:
Um eine MySQL-Datenbank als "Source of Truth" zu nutzen, müssen wir den JavaScript-Code (Node.js) mit einem Datenbank-Treiber wie mysql2 verbinden. Die Datengrundlage zur Prüfung liegt in einer MySQL Datenbank. Der Algorithmus muss hierbei besonders auf den Hausnummernbereich achten, da diese oft als Intervalle (z. B. 1–15 oder nur ungerade Nummern) gespeichert sind.1. Die Datenbank-Struktur (Beispiel)
Damit die Abfrage effizient ist, sollte deine Tabelle etwa so aufgebaut sein: id; zip; city; street; house_start; house_end; type;
Beispiel:
110115; Berlin; Berliner Straße;150;998;e;
220354; Hamburg;Neuer Wall;;;;n;
Vorschlag für den Prozess der Adressprüfung:
Implementierung in Node.js mit MySQL
Wir nutzen mysql2/promise für eine saubere Asynchronität und das Paket levenshtein-edit-distance für die Tippfehler-Toleranz.
JavaScriptconst mysql = require('mysql2/promise');
const levenshtein = require('levenshtein-edit-distance');
/**
* Konfiguration der Datenbank-Verbindung
*/
const dbConfig = {
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'address_db'
};
async function validateAddress(input) {
const connection = await mysql.createConnection(dbConfig);
try {
// 1. Suche nach PLZ und Ort (Exakte Suche zur Performance-Optimierung)
// Wir holen alle Straßen für diese PLZ, um sie später per Fuzzy-Match zu prüfen
const [rows] = await connection.execute(
'SELECT * FROM addresses WHERE zip = ?',
[input.zip.trim()]
);
if (rows.length === 0) {
return { valid: false, message: "PLZ nicht im System gefunden." };
}
let bestMatch = null;
let minDistance = 3; // Max. 3 Zeichen Abweichung erlaubt
// 2. Fuzzy Matching für die Straße
for (const entry of rows) {
const distance = levenshtein(input.street.toLowerCase(), entry.street.toLowerCase());
if (distance < minDistance) {
minDistance = distance;
bestMatch = entry;
}
}
if (!bestMatch) {
return { valid: false, message: "Straße nicht gefunden oder Schreibweise zu ungenau." };
}
// 3. Hausnummern-Check (Bereichsprüfung)
const hn = parseInt(input.houseNumber);
let hnValid = true;
if (bestMatch.house_start && bestMatch.house_end) {
const inRange = (hn >= bestMatch.house_start && hn <= bestMatch.house_end);
// Optional: Prüfung auf gerade/ungerade (Parität)
const parityMatch = bestMatch.type === 'all' ||
(bestMatch.type === 'even' && hn % 2 === 0) ||
(bestMatch.type === 'odd' && hn % 2 !== 0);
if (!inRange || !parityMatch) {
hnValid = false;
}
}
return {
valid: hnValid,
status: hnValid ? "VALID" : "INVALID_HOUSE_NUMBER",
correctedAddress: {
street: bestMatch.street,
zip: bestMatch.zip,
city: bestMatch.city,
houseNumber: input.houseNumber
},
distance: minDistance
};
} finally {
await connection.end();
}
}
// --- BEISPIEL AUFRUF ---
const testAddress = {
street: "Berliner Strase", // Tippfehler
zip: "10115",
houseNumber: "22"
};
validateAddress(testAddress).then(console.log).catch(console.error);
Performance: Wir filtern zuerst nach der zip (Index in der DB setzen!), damit wir nicht tausende Straßen per JavaScript vergleichen müssen, sondern nur die ca. 20-100 Straßen eines Postleitzahlgebiets.
Flexibilität: Der levenshtein-Algorithmus erkennt, dass "Berliner Strase" eigentlich "Berliner Straße" sein soll.
Hausnummern-Logik: Durch die Prüfung von house_start, house_end und dem Typ (even (e)/odd(o)/neutral (n)) werden Fehler zu den Hausnummern abgefangen, wenn jemand eine Hausnummer 99 in einer Straße angibt, die nur bis 50 geht.
Wichtige Datenbank-Optimierung: Damit die Abfrage bei vielen Daten schnell bleibt, sollte in unserer Datenbank noch Indizes auf die Spalten zip und city gelegt werden
SQLCREATE INDEX idx_zip ON addresses(zip);
Zudem sollte die Anfrage erweitert werden, dass in der Datenbank auch nach ähnlich klingenden Straßen und Orten gesucht werden kann. (Soundex)
Kernpunkte des Auftrags
1. Upload-Strecke
• Akzeptierte Formate: CSV, reine Textdateien oder Excel, typischer Umfang 1 000 – 5 000 Zeilen pro Datei. (können aber auch mehr sein) manuelle Möglichkeit zur Dateiprüfung sollte gegeben sein, z.B. bei Dateien mit mehreren Millionen Datensätzen
• Fortschrittsanzeige während des Uploads und der Prüfung
• festgelegter Datenaufbau sollte vorgegeben werden. Eine externe ID in der Datei sollte möglich sein.
2. Prüf-Algorithmus
• Postleitzahl -Überprüfung
• Straßenname -Überprüfung
• Ortsname-Validierung
• Hausnummerncheck (wenn eine Hausnummer vorhanden ist)
Die Routine soll pro Datensatz ein eindeutiges Prüfergebnis (ok / Fehlercode) liefern und idealerweise ein korrigiertes Feld ausgeben, falls klar erkannt.
3. Abrechnung & Payment
• Die ersten 30 Datensätze bleiben kostenfrei.
• Danach automatische Preisberechnung anhand der Anzahl geprüfter Einträge.
• Zahlung via PayPal (Einmalzahlung, keine Abo-Lösung).
4. Ergebnis-Bereitstellung
• Download einer geprüften Datei im Ursprungsformat, ergänzt um Spalten für Status und eventuelle Korrekturvorschläge.
• Kurzer PDF-Report mit Zusammenfassung (Anzahl geprüft, Fehlerverteilung).
5. Administration & Sicherheit
• Einfaches Backend oder Konfig-Datei, um Preise oder Freikontingent anzupassen.
• DSGVO-konforme Verarbeitung: verschlüsselte Übertragung, automatische Löschung der Dateien nach Abschluss.
Lieferumfang
– Voll funktionsfähiger One-Pager (HTML/CSS/JS oder Framework Ihrer Wahl) inkl. responsivem Design.
– Server-Side Logik für Upload, Prüfung und Payment
– Quellcode, Installationshinweise und kurze technische Dokumentation.
- Inklusive lauffähiger Installation auf einem Server (Windows)
Ich freue mich auf Vorschläge, wie Sie das Regelwerk effizient abbilden und die Zahlung reibungslos integrieren können. Bitte nennen Sie relevante Referenzen oder Libraries, die Sie einsetzen möchten.
Details:
Um eine MySQL-Datenbank als "Source of Truth" zu nutzen, müssen wir den JavaScript-Code (Node.js) mit einem Datenbank-Treiber wie mysql2 verbinden. Die Datengrundlage zur Prüfung liegt in einer MySQL Datenbank. Der Algorithmus muss hierbei besonders auf den Hausnummernbereich achten, da diese oft als Intervalle (z. B. 1–15 oder nur ungerade Nummern) gespeichert sind.1. Die Datenbank-Struktur (Beispiel)
Damit die Abfrage effizient ist, sollte deine Tabelle etwa so aufgebaut sein: id; zip; city; street; house_start; house_end; type;
Beispiel:
110115; Berlin; Berliner Straße;150;998;e;
220354; Hamburg;Neuer Wall;;;;n;
Vorschlag für den Prozess der Adressprüfung:
Implementierung in Node.js mit MySQL
Wir nutzen mysql2/promise für eine saubere Asynchronität und das Paket levenshtein-edit-distance für die Tippfehler-Toleranz.
JavaScriptconst mysql = require('mysql2/promise');
const levenshtein = require('levenshtein-edit-distance');
/**
* Konfiguration der Datenbank-Verbindung
*/
const dbConfig = {
host: 'localhost',
user: 'root',
password: 'your_password',
database: 'address_db'
};
async function validateAddress(input) {
const connection = await mysql.createConnection(dbConfig);
try {
// 1. Suche nach PLZ und Ort (Exakte Suche zur Performance-Optimierung)
// Wir holen alle Straßen für diese PLZ, um sie später per Fuzzy-Match zu prüfen
const [rows] = await connection.execute(
'SELECT * FROM addresses WHERE zip = ?',
[input.zip.trim()]
);
if (rows.length === 0) {
return { valid: false, message: "PLZ nicht im System gefunden." };
}
let bestMatch = null;
let minDistance = 3; // Max. 3 Zeichen Abweichung erlaubt
// 2. Fuzzy Matching für die Straße
for (const entry of rows) {
const distance = levenshtein(input.street.toLowerCase(), entry.street.toLowerCase());
if (distance < minDistance) {
minDistance = distance;
bestMatch = entry;
}
}
if (!bestMatch) {
return { valid: false, message: "Straße nicht gefunden oder Schreibweise zu ungenau." };
}
// 3. Hausnummern-Check (Bereichsprüfung)
const hn = parseInt(input.houseNumber);
let hnValid = true;
if (bestMatch.house_start && bestMatch.house_end) {
const inRange = (hn >= bestMatch.house_start && hn <= bestMatch.house_end);
// Optional: Prüfung auf gerade/ungerade (Parität)
const parityMatch = bestMatch.type === 'all' ||
(bestMatch.type === 'even' && hn % 2 === 0) ||
(bestMatch.type === 'odd' && hn % 2 !== 0);
if (!inRange || !parityMatch) {
hnValid = false;
}
}
return {
valid: hnValid,
status: hnValid ? "VALID" : "INVALID_HOUSE_NUMBER",
correctedAddress: {
street: bestMatch.street,
zip: bestMatch.zip,
city: bestMatch.city,
houseNumber: input.houseNumber
},
distance: minDistance
};
} finally {
await connection.end();
}
}
// --- BEISPIEL AUFRUF ---
const testAddress = {
street: "Berliner Strase", // Tippfehler
zip: "10115",
houseNumber: "22"
};
validateAddress(testAddress).then(console.log).catch(console.error);
Performance: Wir filtern zuerst nach der zip (Index in der DB setzen!), damit wir nicht tausende Straßen per JavaScript vergleichen müssen, sondern nur die ca. 20-100 Straßen eines Postleitzahlgebiets.
Flexibilität: Der levenshtein-Algorithmus erkennt, dass "Berliner Strase" eigentlich "Berliner Straße" sein soll.
Hausnummern-Logik: Durch die Prüfung von house_start, house_end und dem Typ (even (e)/odd(o)/neutral (n)) werden Fehler zu den Hausnummern abgefangen, wenn jemand eine Hausnummer 99 in einer Straße angibt, die nur bis 50 geht.
Wichtige Datenbank-Optimierung: Damit die Abfrage bei vielen Daten schnell bleibt, sollte in unserer Datenbank noch Indizes auf die Spalten zip und city gelegt werden
SQLCREATE INDEX idx_zip ON addresses(zip);
Zudem sollte die Anfrage erweitert werden, dass in der Datenbank auch nach ähnlich klingenden Straßen und Orten gesucht werden kann. (Soundex)
Related categories:
JavaScript
Data Processing
Data Entry
Excel
MySQL
HTML
Node.js
German Translator