Bien indexer et rechercher en français?


#1

Bonjour tout le monde,
Je cherche à mettre en place un text search avec possibilité de filtrer par tags.
Le filtrage par tag fonctionne parfaitement, par contre j'ai quelque soucis à obtenir la précision souhaité pour le text search.

Voici mon commandes Sense, incluant analyzer et mapping:

DELETE guide

PUT guide
{
"settings": {
    "analysis": {
      "analyzer": {
        "custom_index_analyzer": {
          "type" : "custom",
          "tokenizer" : "nGram",
          "filter": ["stopwords", "asciifolding" ,"lowercase", "snowball", "elision", "worddelimiter", "stemmer"]
        },
        "custom_search_analyzer": {
          "type" : "custom",
          "tokenizer" : "standard",
          "filter": ["stopwords", "asciifolding" ,"lowercase", "snowball", "elision", "worddelimiter", "stemmer"]
        }
      },
      "tokenizer": {
        "nGram": {
          "type": "nGram",
          "min_gram": 2,
          "max_gram": 20
        }
      }, 
      "filter": {
        "elision": {
          "type":         "elision",
          "articles_case": true,
            "articles": [
              "l", "m", "t", "qu", "n", "s",
              "j", "d", "c", "jusqu", "quoiqu",
              "lorsqu", "puisqu"
            ]
        },
        "snowball": {
          "type": "snowball",
          "language": "French"
        },
        "stopwords": {
          "type":       "stop",
          "stopwords":  "_french_",
          "ignore_case": true
        },
        "worddelimiter": {
          "type": "word_delimiter"
        },
        "stemmer": {
          "type": "stemmer",
          "language": "light_french"
        }
      }
    }
  }
}

PUT guide/commerce/_mapping
{
  "properties": {
    "address": {
      "properties": {
        "line": {
          "type": "string",
          "analyzer": "custom_index_analyzer",
          "search_analyzer": "custom_search_analyzer"
        },
        "city": {
          "type": "string",
          "analyzer": "custom_index_analyzer",
          "search_analyzer": "custom_search_analyzer"
        },
        "postal_code": {
          "type": "string"
        }
      }
    },
    "description": {
      "type": "string",
        "analyzer": "custom_index_analyzer",
        "search_analyzer": "custom_search_analyzer"
    },
    "name": {
      "type": "string",
      "analyzer": "custom_index_analyzer",
      "search_analyzer": "custom_search_analyzer"
    }
    "tags": {
      "type": "string",
      "index": "not_analyzed"
    }
  }
}

# Indexation de documents
PUT guide/commerce/1
{
	"name": "Mon commerce",
	"address": {
		"line": "123 rue Machin",
		"city": "Avignon",
		"postal_code": "84000"
	},
	"description": "Un permier commerce avec des articles.",
	"tags": ["restaurant", "boucherie"]
}

PUT guide/commerce/2
{
	"name": "À la bonne fourchette",
	"address": {
		"line": "450 rue Machin",
		"city": "Avignon",
		"postal_code": "84000"
	},
	"description": "Venez manger du bon poulet.",
	"tags": ["restaurant", "café"]
}

Et voici la recherche que j'effectue:

GET /guide/commerce/_search
{
  "query" : {
    "filtered" : {
      "query": {
        "match": {
          "_all": "article"  
        }
      },
      "filter" : {
        "bool": {
          "must": [
            {"term": {"tags": "restaurant"}},
            {"term": {"tags": "boucherie"}}
          ]
        }
      }
    }
  }
}

Vous pouvez voir que je cherche pour article en espérant que ça match articles au pluriel dans la description de mon commerce avec l'id1.
Malheureusement, je n'ai aucun résultats. Même chose si je table "fourchete" à la place de "fourchette".

D'après ma compréhension, les filtres snowball et stemmer auraient m'aider à supporter ce genre de recherche.

Qu'ai-je mal compris et fait ?
Merci.


(Tanguy) #2

Bonjour,

Le champ _all est un cas un peu à part ( https://www.elastic.co/guide/en/elasticsearch/reference/2.1/mapping-all-field.html#mapping-all-field ), il correspond en gros à une concaténation de toutes les valeurs des champs. La plupart du temps il faut le configurer pour avoir exactement le résultat que l'on souhaite.

Dans ton cas, comme tu n'as pas changé l'analyzer du champ _all par ton analyzer custom c'est celui par défaut qui s'applique (et qui ne gère pas le cas que tu souhaites). Tu peux donc configurer l'analyzer de _all et le changer pour le tien.

Toutefois, je conseille généralement de désactiver _all et d'utiliser une requête de type multi_match qui te permettra de rechercher dans plusieurs champs bien précis à la fois.

Tanguy

Le mieux https://www.elastic.co/guide/en/elasticsearch/reference/2.1/mapping-all-field.html#mapping-all-fieldtu


(David Pilato) #3

J'ajoute à la réponse de Tanguy que j'aime bien personnellement utiliser la fonction copy_to. Elle permet de copier tes textes à chercher en mode "fulltext" vers un champ particulier et du coup de lui associer le ou les analyseurs souhaités.


#4

Génial! Tout fonctionne :slight_smile:
Merci beaucoup pour vous réponses.
Maurice.


(system) #5