2016-09-21 2 views
0

Je souhaite rechercher des documents dans MarkLogic.MarkLogic - Recherche par filtre Max/Min

Mes documents ressemblent:

<product xmlns="myns/products"> 
    <id>3114</id> 
    <materialNo xml:lang="en">1.1160</materialNo> 
    <steelName xml:lang="en">SWRCH24K</steelName> 
    <name xml:lang="en">wire, wire rod for cold heading</name> 
    <chemicalProperties> 
    <chemicalProperty> 
     <element>c</element> 
     <min>0.1900</min> 
     <max>0.2500</max> 
    </chemicalProperty> 
    <chemicalProperty> 
     <element>si</element> 
     <min>0.1000</min> 
     <max>0.3500</max> 
    </chemicalProperty> 
    <chemicalProperty> 
     <element>mn</element> 
     <min>1.3500</min> 
     <max>1.6500</max> 
    </chemicalProperty> 
    <chemicalProperty> 
     <element>p</element> 
     <max>0.0300</max> 
    </chemicalProperty> 
    </chemicalProperties> 
</product> 

donc je veux effectuer une recherche via des valeurs max/min des propriétés chimiques. Pour ce faire j'utiliser cette recherche XQuery (exemple simple):

cts:search(/, cts:and-query(
    (cts:collection-query("test"), 
    cts:element-value-query(
    fn:QName("myns/products", "name"), 
    "wire, wire rod for cold heading"), 
    cts:element-query(
    fn:QName("myns/products", "chemicalProperty"), 
    cts:and-query(
     (cts:element-value-query(
      fn:QName("myns/products", "element"), "c"), 
     cts:or-query(
      (cts:element-range-query(
      fn:QName("myns/products", "max"), "<=", 0.2), 
      cts:and-not-query(
      cts:element-range-query(
       fn:QName("myns/products", "min"), "<=", 0.2), 
      cts:element-value-query(
       fn:QName("myns/products", "max"), "*")))), 
     cts:or-query(
      (cts:element-range-query(
      fn:QName("myns/products", "min"), ">=", 0.1), 
      cts:and-not-query(
      cts:element-range-query(
       fn:QName("myns/products", "max"), ">=", 0.1), 
      cts:element-value-query(
       fn:QName("myns/products", "min"), "*")))))))))) 

Le problème est que la requête ci-dessus renvoie le document de l'échantillon. Les sous-requêtes (et -non) sont là pour vérifier si max/min existe. Dans certains cas, il peut y avoir seulement une valeur minimale ou maximale.

Mais ce document est hors limites ?!

Ma base de données possède des index de plage d'éléments sur min et max. Tous les autres paramètres sont par défaut.

Quel est le problème? Aucune suggestion.

MISE À JOUR

Ok, merci pour les suggestions mais non. La validation de la position de la valeur ne résout pas le problème. Cependant, une solution consiste à supprimer le « et non-requête » et le remplacer par un « et demande » et d'ajouter de nouveaux attributs aux documents:

<chemicalProperty hasMin="0" hasMax="1">... 

l'indexation et l'interrogation de ces attributs fonctionne et renvoie le bon résultats.

+0

Si vous avez une question de suivi, veuillez l'afficher en tant que question SO distincte. Si cette question est pertinente, vous pouvez la lier dans la nouvelle. – wst

Répondre

1

Il est possible qu'en raison de vos paramètres d'index, cts:element-query renvoie true si le match min et max requêtes dans tout<chemicalProperty> dans le même document, pas contraint à un seul <chemicalProperty>. Je m'attendais seulement à voir ceci dans une recherche non filtrée, cependant, et je ne vois pas cette option dans votre appel à cts:search.

Essayez d'abord d'activer element value positions, ce qui devrait permettre à la base de données d'exclure les correspondances de différents éléments à l'aide d'index.

Une solution alternative consiste à utiliser cts:near-query pour contraindre les valeurs dans la requête d'élément par position.

+1

Les positions devraient résoudre ceci. cts: near-query a aussi besoin de ceux-ci, sinon il se comportera comme un cts: and-query. Au moins, lors de l'exécution non filtrée .. – grtjn

+0

@ grtjn Je pense que 'cts: near-query' a besoin de différents index de position que 'cts: element-query'? Mais oui, et je suis un peu confus au sujet de la question filtrée apparente dans la question. Étant donné le comportement, je pense que l'hypothèse la plus sûre pour l'instant est que OP l'a laissé dans l'exemple par accident. – wst

+0

Vous avez raison, 'cts: near-query' nécessite des index de position différents. http://docs.marklogic.com/cts:near-query dit: 'L'index des positions de mots va accélérer les performances des requêtes qui utilisent cts: near-query. L'index des positions de mots des éléments accélérera les performances des requêtes sur les éléments qui utilisent cts: near-query.' – grtjn

0

Le problème semble être que vous essayez d'utiliser des caractères génériques dans les appels cts:element-value-query, mais sans les déclarer génériques. Puisque rien ne correspond au littéral "*", le cts:and-not-query fait le contraire de ce que vous avez l'intention de faire.

Vous voulez quelque chose comme ceci:

cts:element-value-query( fn:QName("myns/products", "max"), "*", "wildcarded")

cts:element-value-query

Alternativement, vous pouvez activer l'un des indices génériques et ML détecte automatiquement les requêtes génériques.

En l'absence de "caractères génériques" ou de "cartes non imprimées", la configuration de la base de données et le texte $ text déterminent le caractère générique. Si la base de données possède des index génériques activés ("recherche de trois caractères", "recherche de deux caractères", "recherche d'un caractère" ou "recherches génériques de fin") et si $ text contient l'un des caractères génériques '?' ou '*', il indique "générique". Sinon, il spécifie "unwildcarded".

+0

Il n'est généralement pas nécessaire de déclarer l'option générique. Si des index génériques sont activés, l'option 'wildcarded' sera implicite s'il y a un caractère générique dans la chaîne de requête. – wst

+0

J'ai supposé de "tous les autres paramètres sont par défaut" qu'aucun des index génériques ont été activés. – BenW