Bonjour,
je suis chargé de mettre en place un moteur de recherche dans une application web (PHP, MySQL) de GED.
Je rencontre la problématique suivante :
L'application GED comporte plusieurs utilisateurs. Chaque utilisateur peut uniquement consulter les documents auxquels il est habilité.
Dans le cas présent, la base de données est constituée comme suit (je vulgarise et simplifie) :
Chaque utilisateur doit pouvoir rechercher un document par son nom de fichier (par exemple) auquel il est habilité.
Le résultat attendu :
J'ai lu qu'il n'est pas permis de réaliser de jointures entre index sous ES, que la philosophie NoSQL != SQL, quelles informations dois-je indexer pour chaque document ? Comment dois-je procéder pour arriver au résultat attendu ?
Je vous remercie de m'avoir lu et j'attends vos précieux conseils, critiques.
Bonjour Samak,
Peux-tu m'en dire plus sur ton niveau en ES ? ça permettra de mieu cibler les points à expliquer.
En préanbule, assure toi d'avoir une version elasticsearch 5.X et non la version installé de base par 100% des gestionnaire de packet, à savoir la 2.X. J'ai eu pas mal de souci à cause de ça.
Il ne faut pas résonner en relationnel en effet, en revanche tu peux imbriquer des structures de données entre elle, je te conseil de regarder les deux types de base de ES qui sont :
nested comparable à du OneToMany
Tu peux donc faire un mapping tel que :
Voici un exemple de mapping :
{
"myindex": {
"mappings": {
"document": {
"properties": {
"fileName": {
"type": "text"
},
"id": {
"type": "integer"
},
"dossier": {
"type": "nested",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "text"
}
}
}
}
}
}
}
}
Cela te donnera des sorties du type :
[
{
'fileName' : 'fichier 1',
'id': 1,
'dossier' : [
{
'id': 1,
'name': 'dossier 1',
},
{
'id': 2,
'name': 'dossier 2',
},
]
}
]
ensuite pour ta query, cela doit être une alliance de MySQL et Elasticsearch, cela doit fonctionner de paire, tu ne feras pas tout avec uniquement Elasticsearch au risque de vraiment t'arracher les cheveux. Garde les rôles suivants :
Elasticsearch se charge de la recherche à proprement parler.
Cela donnera donc (pour un type object) :
GET /myindex/document/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"fileName": {
"query": "keyword"
}
}
},
{
"terms": {
"dossier.id": [
1,
2
]
}
}
]
}
},
"_source": [
"id"
],
"highlight": {
"pre_tags": [
"<strong>"
],
"post_tags": [
"<\/strong>"
],
"fields": {
"fileName": {
"number_of_fragments": 100
}
}
}
}
Ici tu fais une requête sur l'index "myindex" pour le type : "document"
GET /myindex/document/_search
"bool": {
"must": [
{
"match": {
"fileName": {
"query": "keyword"
}
}
},
{
"terms": {
"dossier.id": [
1,
2
]
}
}
]
}
Cette partie dit retourne moi tout les résultats dont le champ "fileName" match avec "keyword" ET dossier.id vaut 1 ou 2.
ensuite tu veux que le resultat te retourne que l'ID (note: cela equivaut à faire SELECT id FROM [...] plutôt que SELECT *) et enfin tu demandes de mettre en highlight là ou il a match.
Attention la requête ci-dessus fonctionne pour un type object !
pour le mapping soumis ci-dessus préfère cette requête. (plus d'info ici)[https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-nested-query.html]
GET /myindex/document/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"fileName": {
"query": "keyword"
}
}
},
"nested" : {
"path" : "dossier",
"query" : {
"bool" : {
"must" : [
{
"terms" : {
"dossier.id" : [1,2]
}
}
]
}
}
}
]
}
},
"_source": [
"id"
],
"highlight": {
"pre_tags": [
"<strong>"
],
"post_tags": [
"<\/strong>"
],
"fields": {
"fileName": {
"number_of_fragments": 100
}
}
}
}
Enfin une fois les résultats retourné, tu auras une liste d'id de document correspondant à ta recherche ! plus qu'à les retrouver dans ta BDD MySQL et les passer à ta view pour les formater comme tu le souhaites
J'espère t'avoir aidé, hésite pas à compléter si tu as besoin d'autres informations.
Bonjour,
je te remercie pour ta réponse et ta réactivité. J'ai en effet, oublié de mentionner que je débute avec Elasticsearch, je n'en connais que quelques principes basiques, et les syntaxes ne me sont que trop peu familières. Partons du principe que je suis débutant.
Pour le coup, j'ai lu davantage la documentation concernant les éléments que tu m'as apportés : le mapping, nested, object.
Je comprends mieux pour le coup, l'orientation que je dois prendre.
J'étais obnubilé par l'idée de vouloir tout faire passer par Elasticsearch, en pensant qu'il était possible de réaliser un filtre sur une recherche à partir d'une autre recherche. Un peu à la manière de reqûetes imbriquées SQL.
Je te remercie encore une fois, je pense que ta réponse est complète, j'essaie d'intégrer toutes ces informations de mon côté et d'implémenter ces réflexions :)
Bonjour et bon courage pour ton apprentissage, je te conseil d'attaquer impérativement les éléments suivants avant de commencer, hésite surtout pas à te faire un index de test avant de te lancer dans la problématique de ton projet.
Une fois avoir couvert cela, tu auras une vision global de ce qu'offre ce merveilleux outil.