From f80453e78dd157cdb5f66a401ea4493eccb95c3d Mon Sep 17 00:00:00 2001 From: David Blackman Date: Tue, 5 May 2020 09:42:08 -0400 Subject: [PATCH 1/2] start of fixing ambiguous streets --- sanitizer/_text_pelias_parser.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/sanitizer/_text_pelias_parser.js b/sanitizer/_text_pelias_parser.js index 8ed3b1baf..8f146e0bf 100644 --- a/sanitizer/_text_pelias_parser.js +++ b/sanitizer/_text_pelias_parser.js @@ -52,6 +52,23 @@ function _sanitize (raw, clean) { return messages; } +function isAmbiguousStreetOrPlaceParse(query, solutions){ + if (!solutions) { + return false; + } + const wholeStreetSolution = solutions.find(solution => { + return solution.pair && + solution.pair[0].label === 'street' && + solution.pair[0].span.body === query; + }); + const wholePlaceSolution = solutions.find(solution => { + return solution.pair && + solution.pair[0].label === 'place' && + solution.pair[0].span.body === query; + }); + return wholeStreetSolution && wholePlaceSolution; +} + function parse (clean) { // parse text @@ -108,6 +125,19 @@ function parse (clean) { } } + // If the parser generated two solutions, one where the whole query was classified as a + // street, and another where it was classified entirely as a place, discard both solutions + // since we don't really know which to use. + // This helps with queries like "wrigley field" that have a word (field) that could be + // a street suffix but is also a likely venue word + if (isAmbiguousStreetOrPlaceParse(t.span.body, t.solutions) && + (parsed_text.street || parsed_text.place)) { + delete parsed_text.street; + delete parsed_text.place; + mask = mask.replace(/S/g, ' '); + mask = mask.replace(/V/g, ' '); + } + // the entire input text as seen by the parser with any postcode classification(s) removed let body = t.span.body.split('') .map((c, i) => (mask[i] !== 'P') ? c : ' ') From a5594d968d128e5e9330c01394353acf190f4a90 Mon Sep 17 00:00:00 2001 From: David Blackman Date: Tue, 5 May 2020 15:29:34 -0400 Subject: [PATCH 2/2] works --- sanitizer/_text_pelias_parser.js | 41 ++++++++++++++-------- test/unit/sanitizer/_text_pelias_parser.js | 5 +++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/sanitizer/_text_pelias_parser.js b/sanitizer/_text_pelias_parser.js index 8f146e0bf..8ae2d4c8b 100644 --- a/sanitizer/_text_pelias_parser.js +++ b/sanitizer/_text_pelias_parser.js @@ -52,25 +52,31 @@ function _sanitize (raw, clean) { return messages; } -function isAmbiguousStreetOrPlaceParse(query, solutions){ +function isAmbiguousStreetOrPlaceParse(solutions){ if (!solutions) { return false; } - const wholeStreetSolution = solutions.find(solution => { + + const topTwoSolutions = _.take(solutions, 2); + const streetOnlySolution = topTwoSolutions.find(solution => { return solution.pair && - solution.pair[0].label === 'street' && - solution.pair[0].span.body === query; + solution.pair.length === 1 && + solution.pair[0].classification.label === 'street'; }); - const wholePlaceSolution = solutions.find(solution => { + const placeOnlySolution = topTwoSolutions.find(solution => { return solution.pair && - solution.pair[0].label === 'place' && - solution.pair[0].span.body === query; + solution.pair.length === 1 && + solution.pair[0].classification.label === 'place'; }); - return wholeStreetSolution && wholePlaceSolution; + + return ( + streetOnlySolution && + placeOnlySolution && + streetOnlySolution.pair[0].span.body === placeOnlySolution.pair[0].span.body + ); } -function parse (clean) { - +function parse (clean) { // parse text let start = new Date(); const t = new Tokenizer(clean.text); @@ -125,12 +131,17 @@ function parse (clean) { } } - // If the parser generated two solutions, one where the whole query was classified as a - // street, and another where it was classified entirely as a place, discard both solutions - // since we don't really know which to use. + // (Theory) If the parser's two top solutions were labeling the entire query as a venue/place, + // and labeling the entire query as a street, then the parse is telling us it's pretty + // ambiguous, so we shouldn't bother boosting street or place matches in our search. + // // This helps with queries like "wrigley field" that have a word (field) that could be - // a street suffix but is also a likely venue word - if (isAmbiguousStreetOrPlaceParse(t.span.body, t.solutions) && + // a street suffix but is also a likely venue word. + // + // (Reality) There's no way to tell if the parser labeled the "whole query" because + // punctuation in the incoming query is unlabeled, so in reality this checks if + // the top two solutions were venue-only and place-only and labeled identical parts of the query + if (isAmbiguousStreetOrPlaceParse(t.solution) && (parsed_text.street || parsed_text.place)) { delete parsed_text.street; delete parsed_text.place; diff --git a/test/unit/sanitizer/_text_pelias_parser.js b/test/unit/sanitizer/_text_pelias_parser.js index fb998eec7..433f1d4b0 100644 --- a/test/unit/sanitizer/_text_pelias_parser.js +++ b/test/unit/sanitizer/_text_pelias_parser.js @@ -308,6 +308,11 @@ module.exports.tests.text_parser = function (test, common) { cases.push(['Air & Space Museum D', { subject: 'Air & Space Museum' }, true]); cases.push(['Air & Space Museum DC', { subject: 'Air & Space Museum' }, true]); + // ambiguous venue + cases.push(['mccarren park', { + subject: 'mccarren park', + }]); + // admin areas cases.push(['N', { subject: 'N' }, true]); cases.push(['Ne', { subject: 'Ne' }, true]);