2010-02-12 3 views
6

J'ai une application où les utilisateurs peuvent choisir des pièces de voiture. Ils choisissent leur véhicule, puis choisissent les attributs du véhicule comme facettes. Après avoir sélectionné leur véhicule, ils peuvent choisir des facettes comme la taille du moteur, par exemple, pour affiner la liste des résultats. Le problème était que tous les documents n'avaient pas une taille de moteur (c'est une valeur vide dans Solr), car cela n'a pas d'importance pour toutes les parties. Par exemple, une taille de moteur importe rarement pour un filtre à air. Donc, même si un utilisateur a choisi 3,5L pour la taille de son moteur, je voulais toujours montrer les filtres à air sur l'écran comme une partie possible de l'utilisateur pourrait choisir. je fait quelques recherches et la requête de la facette suivante fonctionne parfaitement:Comment rechercher des facettes vierges dans un champ de facettes à valeurs multiples et en même temps dans Solr?

enginesize:"3.5" OR enginesize:(*:* AND -enginesize:[* TO *]) 

Cette requête correspond soit 3.5 ou correspondrait à des dossiers où il n'y avait pas de valeur pour le champ Taille du moteur (pas de valeur signifie qu'il n'a pas d'importance, et il correspond à la voiture). Le problème ...

LE PROBLÈME: J'ai récemment créé les champs d'attributs de véhicules à valeurs multiples, afin que je puisse stocker des attributs pour chaque partie sous forme de liste. J'ai alors appliqué la facette à elle, et cela a fonctionné bien. Cependant, le problème est survenu lorsque j'ai appliqué la requête précédemment mentionnée. Pendant que la sélection de la facette motorisée réduisait le nombre de documents affichés uniquement pour les documents ayant cette taille de moteur, les enregistrements (j'utilise également le mot record signifiant document) qui avaient des valeurs vides (c.-à-d. "") Pour engineize n'apparaissaient pas. La même requête ci-dessus ne fonctionne pas pour les facettes multivaluées de la même manière que lorsque engineize était un champ à valeur unique.

Exemple:

<doc> 
    <str name="part">engine mount</str> 
    <arr name="enginesize"> 
    <str/> 
    <str/> 
    <str>3.5</str> 
    <str>3.5</str> 
    <str>3.5</str> 
    <str>3.5</str> 
    <str>3.5</str> 
    </arr> 
<doc> 

<doc> 
    <str name="part">engine bolt</str> 
    <arr name="enginesize"> 
    <str>6</str> 
    <str>6</str> 
    <str>6</str> 
    <str>6</str> 
    <str>6</str> 
    </arr> 
<doc> 

<doc> 
    <str name="part">air filter</str> 
    <arr name="enginesize"> 
    <str/> 
    <str/> 
    <str></str> 
    <str></str> 
    <str></str> 
    <str></str> 
    <str></str> 
    </arr> 
<doc> 

Ce que je cherche est une requête qui retirer les documents 1 et 3 ci-dessus quand je fais une recherche de facette pour la taille du moteur pour 3,5. Le premier document (le montage du moteur) correspond, car il contient la valeur dans l'un des champs à plusieurs valeurs "engineize" que je cherche (contient 3.5 dans l'un des champs). Cependant, le troisième document pour le filtre à air n'est pas renvoyé à cause des valeurs <str> vides. Je ne veux pas renvoyer le second document du tout car il ne correspond pas à la valeur de la facette

Je souhaite fondamentalement une requête qui va correspondre à des valeurs de chaîne vides pour une facette donnée et également correspondre à la valeur réelle, donc j'obtiens les deux documents retournés. Est-ce que quelqu'un a une requête qui renvoie le document 1 et le document 3 (le support du moteur et le filtre à air), mais pas le document du boulon du moteur?

J'ai essayé ce qui suit sans succès (y compris celui au sommet de cette question):

// returns everything 
enginesize:"3.5" OR (enginesize:[* TO *]) 
// only returns document 1 
enginesize:"3.5" OR (enginesize:["" TO ""] AND -enginesize:"3.5") 
// only returns document 1 
enginesize:"3.5" OR (enginesize:"") 

les données I importé ci-dessus à l'aide d'un fichier CSV, je définir le champ keepEmpty=true. J'ai essayé au lieu d'insérer manuellement un espace dans le champ quand je généré le fichier CSV (qui vous donnera <str> </str>, au lieu de la précédente, puis retenté les requêtes faisant cela, j'ai obtenu les résultats suivants:.

// returns document 1 
enginesize:"3.5" OR enginesize:(*:* AND -enginesize:[* TO *]) 
// returns all documents 
enginesize:"3.5" OR (enginesize:["" TO ""] AND -enginesize:"3.5") 
// returns all documents 
enginesize:"3.5" OR (enginesize:"") 

quelqu'un at-il une question qui fonctionnerait pour les deux cas, si j'ai un espace que la valeur vide ou tout simplement aucune valeur

Répondre

8

? que diriez-vous de changer la façon dont vous indexez, au lieu de la façon dont vous interrogez?

lieu d'essayer d'indexer "la taille du moteur n'a pas d'importance" comme un enregistrement vide, l'indexer comme "ANY".

Ensuite, votre requête devient simplement enginesize: « 3.5 » OR (enginesize: ANY)

+0

Pas besoin de ça, voir http://stackoverflow.com/a/35646250/13365 – neu242

1

je viens jouer avec cela et trouvé un hint qui semble faire l'affaire pour moi. traduit à votre requête, il devrait être:

enginesize:"3.5" OR (-enginesize:["" TO *]) 

HTH,

Andi


mise à jour: après quelques tests plus je ne pense pas que cela fonctionne de manière fiable - pour certains indices, il a dû être l'inverse et sans le signe moins, c'est-à-dire enginesize:[* TO ""]. cela peut dépendre du type d'index, s'il est multi-valué ou même des valeurs réelles.

dans tous les cas, il semble trop d'un hack. Je vais probablement résoudre à substituer la valeur vide avec un marqueur spécial ...

Questions connexes