Création d'un nouvel index pour indexer des emails et leurs contenus

Bonjour,

Par le passé nous avons utilisé ES de maniere assez simple, nos index sont composés d'un seul type de document et un champ "content".

Là je cherche à indexer des emails (Sujet, Corps, Expediteur, Date) et le contenu des pièces jointes (PDF, Word, Txt), l'objectif etant de pouvoir ensuite faire des requetes dans des archives de mails.

Avec le changement opéré en 7.0 Removal of mapping types | Elasticsearch Guide [7.15] | Elastic je suis un peu perdu.

Quel serait pour vous le meilleur moyen ?

Créer deux index (un pour email, l'autre pour attachment) et comment recouper les deux avec une sorte de Jointure ? Ou plus simplement un seul index de la même façon (1 email avec 2 piece jointes seraient représentés par 3 documents dans ES).

Merci

Yathus

Bienvenue !

Si possible, la jointure est à éviter. Mais l'idée de 2 index, pourquoi pas.

Oui. Ou alors, tu n'indexes que des documents de type pièce jointe. Donc 2 documents dans ton cas.
Chaque document PJ contient alors toutes les données de l'email.

Les questions à se poser est à propos de ton cas d'utilisation:

  • Que cherchent les utilisateurs finaux ?
  • Quel "type" d'objet est-ce ?
  • Dois-tu retourner un objet email ? Un objet PJ ? Les deux ?
  • Quels sont les champs/données sur lesquels la recherche doit s'appliquer ?
  • Y a t'il des MAJ des emails à faire ou bien peut-on les considérer comme immuables ?

Merci pour vos idées, pour répondre à vos questions :

  • l'objectif est d'archiver des emails dans un stockage à part du serveur de messagerie, on considère effectivement que c'est immuable, il n'y aura pas de mise à jour d'un document déjà classé (sauf à ajouter des critères de classement mais dans ce cas là on peut imaginer tout réindexer)
  • les utilisateurs finaux vont chercher surement avec l'adresse mail de la personne (ou une partie dans le cas d'une société par exemple), utiliser la date (ou une période), chercher dans le contenu du mail et/ou du sujet (exemple : facture / devis / commande), peut être une référence, un nom de fichier joint ou tout contenu d'un fichier joint.
  • autant que possible je souhaite récréer des discussions, à savoir la conversation. Un email aura donc peut etre un parent et un enfant.
  • au niveau du retour, je compte recuperer la liste des ID "unique" pour ensuite aller chercher les données stockées ailleurs (SGBDR + stockage classique pour les fichiers).

Globalement je sais assez bien ce que je veux, je bute plutot sur la modélisation ES que je ne maitrise pas assez bien, il y a peut etre des documentations que j'ai raté ?

Bonjour,

A mon avis cela dépend vraiment du besoin de la jointure si tu peux le décrire (par exemple : pour une personne x savoir combien de pièce jointes, durée d'envoie des emails, etc.) L'histoire de jointure est a oublié, parce qu'on va sacrifier la puissance de recherche d'elastic.

A l'époque elastic supporté les jointures mais ce n'est plus supporté, donc à éviter.
Le plus juducieux je pense est de créer un index 'mail' est d'indexer tout en un seul document, avoir quelques chose similaire à :

{
  "@timestamp": "2021-10-05T10:10:00Z",
  "from": "jhon.smith@domain.com",
  "to": "jhon.john@domain.com",
  "subject": "modeling es index",
  "attached": "modeling_es.pdf",
  "message": "lorem ipsum...."
}

Avec cette approche utiliser le type keyword sur les champs from et to pour faire des aggregats par exemple. Après utiliser par exemple Transform API et par ici des exemples de Transforms API

ou bien si tu veux vraiment séparer les deux indexes (mail et attachment), il y a ce principe Entity-centric c'est ancien mais ça donne une idée comment le faire en amont.

Marone,

Si je reprends ton exemple je partirai plutôt là dessus du coup, pour un mail avec 2 pièces jointes :

{
  "@timestamp": "2021-10-05T10:10:00Z",
  "id": 1,
  "uid" : "xxx-xxxx-xxxx-xxxxx",
  "rank" : 0,
  "attachment" : false,
  "from": "jhon.smith@domain.com",
  "to": "jhon.john@domain.com",
  "subject": "modeling es index",
  "attached": "",
  "content": "lorem ipsum...."
}
{
  "@timestamp": "2021-10-05T10:10:00Z",
  "id": 2,
  "uid" : "xxx-xxxx-xxxx-xxxxx",
  "rank" : 1,
  "attachment" : true,
  "from": "jhon.smith@domain.com",
  "to": "jhon.john@domain.com",
  "subject": "modeling es index",
  "attached": "finename-1.pdf",
  "content": ""
}
{
  "@timestamp": "2021-10-05T10:10:00Z",
  "id": 3,
  "uid" : "xxx-xxxx-xxxx-xxxxx",
  "rank" : 2,
  "from": "jhon.smith@domain.com",
  "to": "jhon.john@domain.com",
  "subject": "modeling es index",
  "attached": "finename-1.pdf",
  "content": ""
}

Du coup si je ne veux pas faire de recherche dans le contenu des pièces jointes, je prends le rank = 0
Bien sur je passe en ingest-attachment, l'objectif etant de ne pas stocker de fichier dans ES, je indexer le contenu.
Je passe aussi les champs "To" / "CC" en tableau de string car on peut avoir plusieurs valeurs possible.

Je trouve çà redondant de mettre les champs "TO" par exemple, mais je ne vois pas comment faire si je veux par exemple rechercher les emails avec PJ envoyés à une personne en particulier...

Qu'en pensez vous ?

Si si. C'est toujours supporté. Joining queries | Elasticsearch Guide [7.15] | Elastic
C'est juste un truc que je ne recommande pas de base.

Perso, comme le besoin est de ramener un identifiant de conversation, je ferais un truc de ce genre:

{
  "@timestamp": "2021-10-05T10:10:00Z",
  "from": "jhon.smith@domain.com",
  "to": "jhon.john@domain.com",
  "subject": "modeling es index",
  "attached": [ "modeling_es1.pdf",  "modeling_es2.pdf" ],
  "message": "lorem ipsum...."
}

Si le volume des PJ est trop élevé, je ferais peut-être alors du nested pour le champ attached afin qu'Elasticsearch indexe au final 3 documents.

Pour les requêtes, je te conseille de ne récupérer que le field uid, pour éviter d'avoir à ramener trop de données par le réseau.

Oui mais la redondance a du bon à mon avis. C'est très bien de dupliquer la donnée si le use case le nécessite. Ici, si tu veux chercher un sous message par son auteur, il te faut l'auteur dans chaque sous message.

En conclusion soit je crée un doc ES par message et je mets un tableau des noms de fichiers et à l'ajout dans l'index je passe en "injest attachment" les X fichiers, soit je crée un message pour l'email puis autant de messages qu'il y a de pièces jointes et à l'ajout dans l'index je crée donc X+1 docs.

J'ai bon ?

Qu'est ce que la notion de "nested" ?

merci @dadoonet pour l'info je me suis basé sur ce lien Handling Relationships :stuck_out_tongue:

@Yathus je pense la modélisation de @dadoonet est plus adéquat d'utiliser une liste pour les attached, après pour ton use case pour rechercher les emails avec PJ envoyés à une personne, tu va faire une visualisation de type metrics dans kibana, et puis dans la barre de recherche filtrer sur le champ TO à une personne, càd la requête KQL est la suivante : to:"john.smith@example.com" ça va te faire un count sur les émails envoyés à john.smith@example.com, ou bien pour voir une aggrégation pour chaque mail (pour chaque utilisateur), utilise dans ce cas TSVB table qui te permet de faire plusieurs agregat en un seul tableau.
C'est juste des idées essai sur un PoC pour confirmer :slight_smile:

Je reviens sur la remarque de redondant, oui tu va stocker plus de données par rapport à un stockage classique relationnel, mais tu gagneras en terme de rapidité de recherche, c'est ça l'avantage.

1 Like

Merci à tous les deux, je vais tester maintenant ! Il ne me reste plus qu'a charger quelques millions de messages :sweat_smile:

2 Likes