From e3c9473374f3181f00a70c1a91d2d16b9fe8e6b6 Mon Sep 17 00:00:00 2001 From: Victor Shcherb Date: Sun, 24 Jul 2016 17:49:18 +0200 Subject: [PATCH] Improve full-text search --- .../osmand/search/core/SearchCoreFactory.java | 107 +++++----------- .../net/osmand/search/core/SearchPhrase.java | 118 +++++++++++------- .../net/osmand/search/core/SearchResult.java | 5 +- .../net/osmand/search/core/SearchWord.java | 4 - .../search/QuickSearchDialogFragment.java | 14 +-- 5 files changed, 118 insertions(+), 130 deletions(-) diff --git a/OsmAnd-java/src/net/osmand/search/core/SearchCoreFactory.java b/OsmAnd-java/src/net/osmand/search/core/SearchCoreFactory.java index f4dedd9c48..0a9a1d18e5 100644 --- a/OsmAnd-java/src/net/osmand/search/core/SearchCoreFactory.java +++ b/OsmAnd-java/src/net/osmand/search/core/SearchCoreFactory.java @@ -14,7 +14,6 @@ import java.util.Map.Entry; import java.util.TreeSet; import net.osmand.CollatorStringMatcher.StringMatcherMode; -import net.osmand.LocationConvert; import net.osmand.ResultMatcher; import net.osmand.binary.BinaryMapAddressReaderAdapter; import net.osmand.binary.BinaryMapIndexReader; @@ -105,7 +104,7 @@ public class SearchCoreFactory { sr.objectType = ObjectType.REGION; sr.location = bmir.getRegionCenter(); sr.preferredZoom = 6; - if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { + if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) { resultMatcher.publish(sr); } else if (phrase.getNameStringMatcher().matches(sr.localeName)) { resultMatcher.publish(sr); @@ -148,7 +147,7 @@ public class SearchCoreFactory { @Override public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException { - if (phrase.getLastWord().isEmpty()) { + if (!phrase.isUnknownSearchWordPresent()) { return false; } // phrase.isLastWord(ObjectType.CITY, ObjectType.VILLAGE, ObjectType.POSTCODE) || phrase.isLastWord(ObjectType.REGION) @@ -180,7 +179,7 @@ public class SearchCoreFactory { } } } - if (phrase.isNoSelectedType() && bbox != null && phrase.getLastWord().length() > 0) { + if (phrase.isNoSelectedType() && bbox != null && phrase.isUnknownSearchWordPresent()) { NameStringMatcher nm = phrase.getNameStringMatcher(); resArray.clear(); resArray = townCitiesQR.queryInBox(bbox, resArray); @@ -210,7 +209,7 @@ public class SearchCoreFactory { private void searchByName(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException { - if(phrase.getRadiusLevel() > 1 || phrase.getLastWord().length() > 3) { + if(phrase.getRadiusLevel() > 1 || phrase.getUnknownSearchWordLength() > 3) { final boolean locSpecified = phrase.getLastTokenLocation() != null; LatLon loc = phrase.getLastTokenLocation(); final QuadRect streetBbox = phrase.getRadiusBBoxToSearch(DEFAULT_ADDRESS_BBOX_RADIUS); @@ -314,7 +313,9 @@ public class SearchCoreFactory { BinaryMapIndexReader r = offlineIterator.next(); currentFile[0] = r; SearchRequest req = BinaryMapIndexReader.buildAddressByNameRequest(rm, phrase - .getLastWord().toLowerCase(), StringMatcherMode.CHECK_STARTS_FROM_SPACE); + .getUnknownSearchWord().toLowerCase(), + phrase.isUnknownSearchWordComplete() ? StringMatcherMode.CHECK_EQUALS_FROM_SPACE : + StringMatcherMode.CHECK_STARTS_FROM_SPACE); if (locSpecified) { req.setBBoxRadius(loc.getLatitude(), loc.getLongitude(), phrase.getRadiusSearch(DEFAULT_ADDRESS_BBOX_RADIUS * 10)); } @@ -335,16 +336,17 @@ public class SearchCoreFactory { @Override public boolean search(final SearchPhrase phrase, final SearchResultMatcher resultMatcher) throws IOException { - if(phrase.getLastWord().length() == 0) { + if(!phrase.isUnknownSearchWordPresent()) { return false; } final BinaryMapIndexReader[] currentFile = new BinaryMapIndexReader[1]; Iterator offlineIterator = phrase.getRadiusOfflineIndexes(BBOX_RADIUS, SearchPhraseDataType.POI); + final NameStringMatcher nm = phrase.getNameStringMatcher(); QuadRect bbox = phrase.getRadiusBBoxToSearch(BBOX_RADIUS_INSIDE); SearchRequest req = BinaryMapIndexReader.buildSearchPoiRequest( (int)bbox.centerX(), (int)bbox.centerY(), - phrase.getLastWord(), + phrase.getUnknownSearchWord(), (int)bbox.left, (int)bbox.right, (int)bbox.top, (int)bbox.bottom, new ResultMatcher() { @@ -357,6 +359,11 @@ public class SearchCoreFactory { SearchResult sr = new SearchResult(phrase); sr.otherNames = object.getAllNames(true); sr.localeName = object.getName(phrase.getSettings().getLang(), true); + if(phrase.isUnknownSearchWordComplete()) { + if(!nm.matches(sr.localeName) || !nm.matches(sr.otherNames)) { + return false; + } + } sr.object = object; sr.preferredZoom = 17; sr.file = currentFile[0]; @@ -364,7 +371,7 @@ public class SearchCoreFactory { if(object.getSubType().equals("city") || object.getSubType().equals("country")) { sr.priorityDistance = SEARCH_AMENITY_BY_NAME_CITY_PRIORITY_DISTANCE; - sr.preferredZoom = object.getSubType().equals("country") ? 8 : 13; + sr.preferredZoom = object.getSubType().equals("country") ? 7 : 13; } else if(object.getSubType().equals("town")) { sr.priorityDistance = SEARCH_AMENITY_BY_NAME_TOWN_PRIORITY_DISTANCE; } else { @@ -395,7 +402,7 @@ public class SearchCoreFactory { @Override public int getSearchPriority(SearchPhrase p) { if(p.hasObjectType(ObjectType.POI) || - p.getLastWord().length() == 0) { + !p.isUnknownSearchWordPresent()) { return -1; } if(p.hasObjectType(ObjectType.POI_TYPE)) { @@ -405,7 +412,7 @@ public class SearchCoreFactory { return -1; } } - if(p.getLastWord().length() > 3 || p.getRadiusLevel() > 1) { + if(p.getUnknownSearchWordLength() > 3 || p.getRadiusLevel() > 1) { return SEARCH_AMENITY_BY_NAME_API_PRIORITY_IF_3_CHAR; } return -1; @@ -435,11 +442,11 @@ public class SearchCoreFactory { }); NameStringMatcher nm = phrase.getNameStringMatcher(); for (PoiFilter pf : topVisibleFilters) { - if (Algorithms.isEmpty(phrase.getLastWord()) || nm.matches(pf.getTranslation())) { + if (!phrase.isUnknownSearchWordPresent() || nm.matches(pf.getTranslation())) { results.add(pf); } } - if (!Algorithms.isEmpty(phrase.getLastWord())) { + if (phrase.isUnknownSearchWordPresent()) { Iterator> it = translatedNames.entrySet().iterator(); while (it.hasNext()) { Entry e = it.next(); @@ -465,7 +472,7 @@ public class SearchCoreFactory { if (p.hasObjectType(ObjectType.POI) || p.hasObjectType(ObjectType.POI_TYPE)) { return -1; } - if(!p.isNoSelectedType() && p.getLastWord().isEmpty()) { + if(!p.isNoSelectedType() && !p.isUnknownSearchWordPresent()) { return -1; } return SEARCH_AMENITY_TYPE_API_PRIORITY; @@ -564,7 +571,7 @@ public class SearchCoreFactory { res.localeName = object.getSubType(); } } - if (!Algorithms.isEmpty(phrase.getLastWord()) + if (phrase.isUnknownSearchWordPresent() && !(ns.matches(res.localeName) || ns.matches(res.otherNames))) { return false; } @@ -628,7 +635,7 @@ public class SearchCoreFactory { // streets related to city continue; } - if (!Algorithms.isEmpty(phrase.getLastWord()) + if (phrase.isUnknownSearchWordPresent() && !(nm.matches(res.localeName) || nm.matches(res.otherNames))) { continue; } @@ -697,7 +704,7 @@ public class SearchCoreFactory { if(s != null) { BinaryMapIndexReader file = phrase.getLastSelectedWord().getResult().file; - String lw = phrase.getLastWord(); + String lw = phrase.getUnknownSearchWord(); NameStringMatcher sm = phrase.getNameStringMatcher(); if (cacheBuilding != s) { cacheBuilding = s; @@ -813,12 +820,12 @@ public class SearchCoreFactory { @Override public boolean search(SearchPhrase phrase, SearchResultMatcher resultMatcher) throws IOException { - if(phrase.getLastWord().length() == 0) { + if(!phrase.isUnknownSearchWordPresent()) { return false; } boolean parseUrl = parseUrl(phrase, resultMatcher); if(!parseUrl) { - parseLocation2(phrase, resultMatcher); + parseLocation(phrase, resultMatcher); } return super.search(phrase, resultMatcher); } @@ -1106,23 +1113,16 @@ public class SearchCoreFactory { } } - private void parseLocation2(SearchPhrase phrase, SearchResultMatcher resultMatcher) { - String lw = phrase.getLastWord(); - SearchWord sw = phrase.getLastSelectedWord(); - LatLon l = null; - if (sw != null && sw.getType() == ObjectType.UNKNOWN_NAME_FILTER) { - l = parseLocation(sw.getWord() + ", " + lw); - } - if (l == null) { - l = parseLocation(lw); - } + private void parseLocation(SearchPhrase phrase, SearchResultMatcher resultMatcher) { + String lw = phrase.getUnknownSearchPhrase(); + LatLon l = parseLocation(lw); if (l != null) { SearchResult sp = new SearchResult(phrase); sp.priority = SEARCH_LOCATION_PRIORITY; sp.object = sp.location = l; sp.localeName = ((float) sp.location.getLatitude()) + ", " + ((float) sp.location.getLongitude()); sp.objectType = ObjectType.LOCATION; - sp.wordsSpan = 2; + sp.wordsSpan = lw; resultMatcher.publish(sp); } else if (phrase.isNoSelectedType()) { LatLon ll = parsePartialLocation(lw); @@ -1138,59 +1138,16 @@ public class SearchCoreFactory { } } - private void parseLocation(SearchPhrase phrase, SearchResultMatcher resultMatcher) { - String lw = phrase.getLastWord(); - SearchWord sw = phrase.getLastSelectedWord(); - double dd = LocationConvert.convert(lw, false); - if(!Double.isNaN(dd)) { - double pd = Double.NaN; - if(sw != null && sw.getType() == ObjectType.UNKNOWN_NAME_FILTER) { - if(isKindOfNumber(sw.getWord())) { - pd = LocationConvert.convert(sw.getWord(), false); - } - } - if(!Double.isNaN(pd)) { - SearchResult sp = new SearchResult(phrase); - sp.priority = SEARCH_LOCATION_PRIORITY; - sp.object = sp.location = new LatLon(pd, dd); - sp.localeName = ((float)sp.location.getLatitude()) +" " + ((float) sp.location.getLongitude()); - sp.objectType = ObjectType.LOCATION; - sp.wordsSpan = 2; - resultMatcher.publish(sp); - } else if (phrase.isNoSelectedType()) { - SearchResult sp = new SearchResult(phrase); - sp.priority = SEARCH_LOCATION_PRIORITY; - sp.object = sp.location = new LatLon(dd, 0); - sp.localeName = ((float) sp.location.getLatitude()) + " "; - sp.objectType = ObjectType.PARTIAL_LOCATION; - resultMatcher.publish(sp); - } - } - } private boolean parseUrl(SearchPhrase phrase, SearchResultMatcher resultMatcher) { - String text = phrase.getLastWord(); + String text = phrase.getUnknownSearchPhrase(); GeoParsedPoint pnt = GeoPointParserUtil.parse(text); - int wordsSpan= 1; - List lst = phrase.getWords(); - for (int i = lst.size() - 1; i >= 0 && (pnt == null || !pnt.isGeoPoint()); i--) { - SearchWord w = lst.get(i); - if (w.getType() != ObjectType.UNKNOWN_NAME_FILTER) { - break; - } - text = w.getWord() + "," + text; - wordsSpan++; - pnt = GeoPointParserUtil.parse(text); - if (pnt != null && pnt.isGeoPoint()) { - break; - } - } if(pnt != null && pnt.isGeoPoint()) { SearchResult sp = new SearchResult(phrase); sp.priority = 0; sp.object = pnt; - sp.wordsSpan = wordsSpan; + sp.wordsSpan = text; sp.location = new LatLon(pnt.getLatitude(), pnt.getLongitude()); sp.localeName = ((float)pnt.getLatitude()) +", " + ((float) pnt.getLongitude()); if(pnt.getZoom() > 0) { diff --git a/OsmAnd-java/src/net/osmand/search/core/SearchPhrase.java b/OsmAnd-java/src/net/osmand/search/core/SearchPhrase.java index 1744306c30..8f522b51a8 100644 --- a/OsmAnd-java/src/net/osmand/search/core/SearchPhrase.java +++ b/OsmAnd-java/src/net/osmand/search/core/SearchPhrase.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; +import java.util.regex.Pattern; import net.osmand.CollatorStringMatcher; import net.osmand.CollatorStringMatcher.StringMatcherMode; @@ -21,13 +22,19 @@ import net.osmand.util.MapUtils; public class SearchPhrase { private List words = new ArrayList<>(); - private String lastWord = ""; + private List unknownWords = new ArrayList<>(); + private String unknownSearchWordTrim; + private String unknownSearchPhrase = ""; + private NameStringMatcher sm; private SearchSettings settings; private List indexes; - private String lastWordTrim; + private QuadRect cache1kmRect; + private boolean unknownSearchWordComplete; private static final String DELIMITER = ","; + private static final String ALLDELIMITERS = "\\s|,"; + private static final Pattern reg = Pattern.compile(ALLDELIMITERS); public enum SearchPhraseDataType { @@ -50,24 +57,40 @@ public class SearchPhrase { sp.words = new ArrayList<>(this.words); leftWords = leftWords.subList(leftWords.size(), leftWords.size()); } - if (!restText.contains(DELIMITER)) { - sp.lastWord = restText; + for(SearchWord w : leftWords) { + if(restText.startsWith(w.getWord() + DELIMITER)) { + sp.words.add(w); + restText = restText.substring(w.getWord().length() + DELIMITER.length()).trim(); + } else { + break; + } + } + sp.unknownSearchPhrase = restText; + sp.unknownWords.clear(); + + if (!reg.matcher(restText).find()) { + sp.unknownSearchWordTrim = sp.unknownSearchPhrase.trim(); } else { - for(SearchWord w : leftWords) { - if(restText.startsWith(w.getWord() + DELIMITER)) { - sp.words.add(w); - restText = restText.substring(w.getWord().length() + DELIMITER.length()).trim(); - } else { - break; + sp.unknownSearchWordTrim = ""; + String[] ws = restText.split(ALLDELIMITERS); + for (int i = 0; i < ws.length ; i++) { + String wd = ws[i].trim(); + if (wd.length() > 0) { + if (i == 0) { + sp.unknownSearchWordTrim = wd; + } else { + sp.unknownWords.add(wd); + } } } - String[] ws = restText.split(DELIMITER); - for (int i = 0; i < ws.length - 1; i++) { - sp.words.add(new SearchWord(ws[i].trim())); - } - sp.lastWord = ws[ws.length - 1]; } - sp.lastWordTrim = sp.lastWord.trim(); + sp.unknownSearchWordComplete = sp.unknownWords.size() > 0; + if (text.length() > 0 && !sp.unknownSearchWordComplete) { + char ch = text.charAt(text.length() - 1); + sp.unknownSearchWordComplete = ch == ' ' || ch == ',' || ch == '\r' || ch == '\n' + || ch == ';'; + } + return sp; } @@ -76,7 +99,31 @@ public class SearchPhrase { return words; } + + public boolean isUnknownSearchWordComplete() { + return unknownSearchWordComplete; + } + + + public List getUnknownSearchWords() { + return unknownWords; + } + public String getUnknownSearchWord() { + return unknownSearchWordTrim; + } + + public String getUnknownSearchPhrase() { + return unknownSearchPhrase; + } + + public boolean isUnknownSearchWordPresent() { + return unknownSearchWordTrim.length() > 0; + } + + public int getUnknownSearchWordLength() { + return unknownSearchWordTrim.length() ; + } public QuadRect getRadiusBBoxToSearch(int radius) { @@ -188,14 +235,8 @@ public class SearchPhrase { public SearchPhrase selectWord(SearchResult res) { SearchPhrase sp = new SearchPhrase(this.settings); - sp.words.addAll(this.words); - while(res.wordsSpan > 1) { - if(sp.words.size() > 0) { - sp.words.remove(sp.words.size() - 1); - } - res.wordsSpan--; - } - SearchWord sw = new SearchWord(res.localeName.trim(), res); + sp.words.addAll(this.words); + SearchWord sw = new SearchWord(res.wordsSpan != null ? res.wordsSpan : res.localeName.trim(), res); sp.words.add(sw); return sp; } @@ -229,16 +270,14 @@ public class SearchPhrase { return false; } - - - - - public NameStringMatcher getNameStringMatcher() { if(sm != null) { return sm; } - sm = new NameStringMatcher(lastWordTrim, StringMatcherMode.CHECK_STARTS_FROM_SPACE); + sm = new NameStringMatcher(unknownSearchWordTrim, + (unknownSearchWordComplete ? + StringMatcherMode.CHECK_EQUALS_FROM_SPACE : + StringMatcherMode.CHECK_STARTS_FROM_SPACE)); return sm; } @@ -261,7 +300,7 @@ public class SearchPhrase { sb.append(s.getWord()).append(DELIMITER.trim() + " "); } if(includeLastWord) { - sb.append(lastWord); + sb.append(unknownSearchPhrase); } return sb.toString(); } @@ -269,11 +308,11 @@ public class SearchPhrase { public String getTextWithoutLastWord() { StringBuilder sb = new StringBuilder(); List words = new ArrayList<>(this.words); - if(Algorithms.isEmpty(lastWordTrim) && words.size() > 0) { + if(Algorithms.isEmpty(unknownSearchWordTrim) && words.size() > 0) { words.remove(words.size() - 1); } for(SearchWord s : words) { - sb.append(s.getWord()).append(", "); + sb.append(s.getWord()).append(DELIMITER.trim() + " "); } return sb.toString(); } @@ -283,7 +322,7 @@ public class SearchPhrase { for(SearchWord s : words) { sb.append(s.getWord()).append(" [" + s.getType() + "], "); } - sb.append(lastWord); + sb.append(unknownSearchPhrase); return sb.toString(); } @@ -297,12 +336,7 @@ public class SearchPhrase { } public boolean isEmpty() { - return words.isEmpty() && lastWord.isEmpty(); - } - - - public String getLastWord() { - return lastWordTrim; + return words.isEmpty() && unknownSearchPhrase.isEmpty(); } @@ -369,8 +403,8 @@ public class SearchPhrase { private CollatorStringMatcher sm; - public NameStringMatcher(String lastWordTrim, StringMatcherMode checkStartsFromSpace) { - sm = new CollatorStringMatcher(lastWordTrim, StringMatcherMode.CHECK_STARTS_FROM_SPACE); + public NameStringMatcher(String lastWordTrim, StringMatcherMode mode) { + sm = new CollatorStringMatcher(lastWordTrim, mode); } public boolean matches(Collection map) { diff --git a/OsmAnd-java/src/net/osmand/search/core/SearchResult.java b/OsmAnd-java/src/net/osmand/search/core/SearchResult.java index b3dea29aef..191d49937c 100644 --- a/OsmAnd-java/src/net/osmand/search/core/SearchResult.java +++ b/OsmAnd-java/src/net/osmand/search/core/SearchResult.java @@ -17,6 +17,7 @@ public class SearchResult { public double priority; public double priorityDistance; + public SearchResult(SearchPhrase sp) { this.requiredSearchPhrase = sp; } @@ -39,8 +40,8 @@ public class SearchResult { public Object relatedObject; public double distRelatedObjectName; - public int wordsSpan = 1; - + public String wordsSpan ; + public SearchResult preciseSearchResult; diff --git a/OsmAnd-java/src/net/osmand/search/core/SearchWord.java b/OsmAnd-java/src/net/osmand/search/core/SearchWord.java index 2aba058ba3..59a896e218 100644 --- a/OsmAnd-java/src/net/osmand/search/core/SearchWord.java +++ b/OsmAnd-java/src/net/osmand/search/core/SearchWord.java @@ -6,10 +6,6 @@ public class SearchWord { private String word; private SearchResult result; - public SearchWord(String word) { - this.word = word.trim(); - } - public SearchWord(String word, SearchResult res) { this.word = word.trim(); this.result = res; diff --git a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java index 3dd227be58..4a703273b0 100644 --- a/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java +++ b/OsmAnd/src/net/osmand/plus/search/QuickSearchDialogFragment.java @@ -155,8 +155,8 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC OsmandSettings settings = app.getSettings(); AbstractPoiType abstractPoiType = (AbstractPoiType) searchPhrase.getLastSelectedWord().getResult().object; PoiUIFilter filter = new PoiUIFilter(abstractPoiType, app, ""); - if (!Algorithms.isEmpty(searchPhrase.getLastWord())) { - filter.setFilterByName(searchPhrase.getLastWord()); + if (!Algorithms.isEmpty(searchPhrase.getUnknownSearchWord())) { + filter.setFilterByName(searchPhrase.getUnknownSearchWord()); } app.getPoiFilters().clearSelectedPoiFilters(); app.getPoiFilters().addSelectedPoiFilter(filter); @@ -352,7 +352,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC sr.objectType = ObjectType.FAVORITE; sr.location = new LatLon(point.getLatitude(), point.getLongitude()); sr.preferredZoom = 17; - if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { + if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) { resultMatcher.publish(sr); } else if (phrase.getNameStringMatcher().matches(sr.localeName)) { resultMatcher.publish(sr); @@ -363,7 +363,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC @Override public int getSearchPriority(SearchPhrase p) { - if(!p.isNoSelectedType() || p.getLastWord().isEmpty()) { + if(!p.isNoSelectedType() || !p.isUnknownSearchWordPresent()) { return -1; } return SEARCH_FAVORITE_API_PRIORITY; @@ -645,7 +645,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC private void addMoreButton() { OsmandApplication app = getMyApplication(); - if ((!searchUICore.getPhrase().getLastWord().isEmpty() || searchUICore.getPhrase().isLastWord(ObjectType.POI_TYPE)) + if ((searchUICore.getPhrase().isUnknownSearchWordPresent() || searchUICore.getPhrase().isLastWord(ObjectType.POI_TYPE)) && searchUICore.getPhrase().getSettings().getRadiusLevel() < 7) { QuickSearchMoreListItem moreListItem = @@ -987,7 +987,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC sr.objectType = ObjectType.RECENT_OBJ; sr.location = new LatLon(point.getLat(), point.getLon()); sr.preferredZoom = 17; - if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { + if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) { resultMatcher.publish(sr); } else if (phrase.getNameStringMatcher().matches(sr.localeName)) { resultMatcher.publish(sr); @@ -1032,7 +1032,7 @@ public class QuickSearchDialogFragment extends DialogFragment implements OsmAndC sr.location = new LatLon(point.getLatitude(), point.getLongitude()); sr.localeRelatedObjectName = info.getFileName(); sr.preferredZoom = 17; - if (phrase.getLastWord().length() <= 1 && phrase.isNoSelectedType()) { + if (phrase.getUnknownSearchWordLength() <= 1 && phrase.isNoSelectedType()) { resultMatcher.publish(sr); } else if (phrase.getNameStringMatcher().matches(sr.localeName)) { resultMatcher.publish(sr);