2009-04-29 8 views
7

J'offre une option de recherche pour mes utilisateurs. Ils peuvent rechercher le nom de la ville. Le problème est que mes noms de villes que j'ai stockés sont des choses comme "Saint Louis". Mais je veux trouver Saint Louis même si l'utilisateur tape "St. Louis" ou "St Louis". Des suggestions sur la façon dont je pourrais créer une table de consultation pour en tenir compte d'une manière ou d'une autre?Question sur la conception de table

+1

base de données utilisez-vous? – Jeremy

+0

Désolé - SQL Server de .Net - c'est un service web, donc la requête me est transmise, je ne reçois pas de l'utilisateur. –

Répondre

5

Créez deux tables.

Un contient tout sur une ville.

On contient un tas de noms pour les villes, et une association de clé étrangère ces naes avec l'id de la première table. Vous avez donc une relation un à plusieurs entre city et city_names.

Maintenant, le seul problème est de distinguer le nom unique, pour chaque ville, qui est le nom préféré. Nous pouvons faire cela de plusieurs façons: 1) la première table pourrait avoir un fk à la deuxième table, qui tient à id du nom préféré. Cela crée une dépendance circulaire, cependant. Donc mieux, 2) il suffit d'ajouter une colonne boolean/bit à la deuxième table, is_preffered.

create table city (id not null primary key, other columns) ; 

create table city_name (
id not null primary key, 
city_id int references city(id), 
name varchar(80), 
is_preferred bool 
) ; 

ensuite pour obtenir tous les noms, le prénom préféré:

select name from city_names where city_id = ? 
    order by is_preffered desc, name; 

Ceci présente un avantage supplémentaire: si vous ne couvre pas toutes les villes et de la ville, vous pouvez utiliser la deuxième table villes/villages/carte comtés vous ne couvrent pas les grandes villes que vous faites:

insert into city_name(city_id, name) values 
($id-for-New-York-City, 'New York'), 
($id-for-New-York-City, 'Manhattan'), 
($id-for-New-York-City, 'Big Apple'), 
($id-for-New-York-City, 'Brooklyn'); 
+0

Je ne vois pas pourquoi j'aurais besoin d'un nom "préféré" - je veux dire, si elles tapent à New York, je vais faire correspondre cela tout de suite. Si elles tapent à Manhattan, et que cela renvoie à New York, pourquoi m'intéresserais-je à l'identifiant de la ville préférée? –

+0

Vous pourriez ne pas; dans ce cas, laissez-le. Je pensais ne pas mettre le nom dans la ville du tout, dans ce cas, nous voudrions un moyen d'afficher le nom "canonique" dans, par exemple, les rapports. – tpdi

+0

Je suis allé avec cette réponse et cela fonctionne comme un charme jusqu'à présent. Ma requête fait une jointure externe avec la table d'alias, et la clause where a "WHERE (lieu.city = 'st louis' OU alias.city_slang = 'st louis')" et je rejoins les tables sur cityname = city_canonical. Ces colonnes changeront bientôt de noms. –

1

Vous pouvez vous intéresser à un moteur de recherche de texte intégral plus complet tel que Apache Lucene/Solr ou Sphinx - qui peut prendre en charge ce type de mappage de chaîne de façon native.

1

Je vois un certain nombre de façons possibles de gérer cela. L'un est un algorithme de recherche soundex qui correspond à la similarité des chaînes anglaises. En outre, cela est pris en charge nativement dans certaines bases de données comme PostgreSQL.

Une autre approche peut simplement consister à offrir à vos utilisateurs une fonctionnalité d'auto-complétion lorsqu'à mesure qu'ils tapent un certain nombre de suggestions apparaissent. De cette façon, les utilisateurs choisiront le nom de la ville de recherche souhaitée de manière intuitive.

3

ce que je ferais est, construire une table abrégée à la normale, ce tracerait un mot ambigu à un seul uniforme l'orthographe vous aurez utiliser dans votre table primaire. Vous pouvez y inclure des fautes d'orthographe courantes et des fautes de frappe.

Avant de rechercher la requête de l'utilisateur, convertissez tous les mots à la forme normale en utilisant ce tableau.

Donc, dans votre cas dans le tableau shorthand-to-normal nous aurons

______________ 
| short|normal | 
|______|_______| 
|St |Saint | 
|St. |Saint | 
+0

Je me demandais à ce sujet. Donc, je voudrais diviser l'entrée sur les espaces (et "."). Ensuite, je ferais une recherche de leur premier terme "st" et reviendrais "saint" - puis utiliser QUE dans ma requête réelle de la table de la ville ... hmmm ... pourrait fonctionner. Merci! –

1

Comme une approche générale, vous pouvez normaliser les éléments à la fois lors de l'insertion et quand les chercher.

Les règles de normalisation pourraient être:

Saint => St 
St. => St 

etc.

Les noms normalisés devraient alors correspondre.

+0

J'ai pensé à cela, mais je ne suis pas sûr d'avoir pu identifier toutes les possibilités. St est juste un. Qu'en est-il de KC, MO pour Kansas City, Missouri? ATL pour Atlanta? Cependant, je pense que je vais devoir faire cela, mais dans une structure de table comme suggéré par d'autres. –

+0

Oui, vous devrez avoir un "dictionnaire" pour votre normalisation de toute façon. Je tapais ma réponse en même temps qu'Elazar Leibovich, de sorte qu'ils sont tous deux assez similaires dans ce qu'ils suggèrent. – Lucero

0

À mon humble avis je laisserais la base de données seule et à la place avoir une liste réduite de villes dans votre application. Plus facile, plus propre et n'exige pas beaucoup d'extra.

+0

La pièce que j'écris est en .Net avec un serveur SQL, et il s'agit simplement d'un service web pour supporter une application iPhone. Le fait est que nous allons les laisser taper n'importe quelle ville dans n'importe quel pays du monde. Je ne veux pas avoir une liste déroulante avec tout ça. Serait inutilisable. –

+0

Ok. Je supposais juste qu'il était jsut dans une application régulière. – DForck42

0

J'aime l'option dans la première réponse.

Une autre idée serait d'avoir une colonne pour les tags pour cette ville que les utilisateurs peuvent mettre à jour.

à savoir

New York City est le nom officiel.

Les étiquettes pour cette ville seraient numérables (Manhattan, NY, NYC, la ville, grosse pomme ..) e.t.c. mais vous ne voudriez pas que tout ce junk dans votre table principale de villes ou pour créer des tables enfant associent et doive faire des jointures. Il suffit donc de le placer dans une colonne et de le rechercher en fonction du terme de recherche, puis de renvoyer le nom approprié s'il est trouvé.

0

Vous pouvez utiliser les propriétés SQL FTS intégrées pour les entrées de thésaurus. Cela vous permet de créer une carte de mots personnalisée à l'intérieur de la recherche en texte intégral. De cette façon, vous pouvez tout conserver à l'intérieur de FTS plutôt que de mélanger FTS et d'autres requêtes.

Je ne sais pas quelle version de SQL que vous utilisez comme differant entre 2005/8 donc il y a une bonne soluce pour 2005/8 ici http://arcanecode.com/2008/05/28/creating-custom-thesaurus-entries-in-sql-server-2005-and-2008-full-text-search/

+0

C'est intéressant. Je n'ai pas accès au registre dans ce cas, mais merci pour le conseil. Je pourrais voir cela utile dans d'autres circonstances. –

+0

Si vous êtes sur sql 2008 synonymns fonctionnerait aussi; et ils n'ont pas besoin du hack de registre. En fonction de votre langue, le fichier XML est ici $ SQL_Server_Install_Path \ Microsoft SQL Server \ MSSQL.1 \ MSSQL \ FTData. Vous pouvez configurer vos villes dans le fichier comme celui-ci de New York Big Apple puis rechargent à l'aide EXEC sys.sp_fulltext_load_thesaurus_file 1033 vous devriez alors être en mesure de tester select * from mytable où contient (*, 'grosse Pomme'). (http://www.simple-talk.com/sql/learn-sql-server/understanding-full-text-indexing-in-sql-server/) – u07ch

+0

pps 1033 = page de code pertinente pour votre région (avec un espace limite) – u07ch

Questions connexes