Lexpage le site qui fait augmenter la moyenne nationale...    —  Anarkhan

Discussions

Go - Enregistrement d'une date d'un xml dans ES

yaug 1450 Spammeur
Bonjour,

Histoire de relancer un peu les topics à code, j'ai besoin d'un petit coup de main.
Je suis en train de développer un crawler de publications scientifiques en go pour enregistrer tout ça dans un Elasticsearch.
Je crawle déjà le titre, l'abstract, les mots clés, les Auteurs etc.
Je sèche un peu sur la date. Par contre.

Je récupère des dates sous cette forme : <dc:date>2011</dc:date>

Grâce à la lib "encoding/xml" et la fonction unmarshal, je charge un struc comme ceci :
type OaiDCItem struct {
Title string `xml:"title"`
Authors []string `xml:"creator"`
Keywords []string `xml:"subject"`
Abstract string `xml:"description"`
Language string `xml:"language"`
Date string `xml:"date"`
}
Jusque là tout va bien, je récupère bien un string comme date, soit "2018-01-01" soit "2018-02" soit "2018", ce sont les 3 formats que je sors du xml que je parse.
Le champ est bien stocké dans un struct et est bien renseigné.

Reste la partie enregistrement.
Côté mapping pour ES j'ai :

const publicationMapping = `
{
"settings":{
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings":{
"dates": {
"type" : "nested",
"properties": {
"key": { "type": "text" },
"date": {"type": "date", "format": "yyyy||yyyy-MM||yyyy-MM-dd" }
}
}
}
}`
J'ai un struct qui fait le lien avec ES :
type PublicationDate struct {
key string `json:"key"`
date time.Time `json:"date"`
}
type Publication struct {
ID string `json:"id"`
Title string `json:"title"`
Type string `json:"type"`
Abstract string `json:"abstract"`
Source string `json:"source"`
Language string `json:"language"`
CreatedAt time.Time `json:"created_at"`
Authors []Author `json:"authors"`
Keywords []string `json:"keywords"`
Identifiers []string `json:"identifiers"`
Dates []PublicationDate `json:"dates"`
}
Ma problématique, c'est donc de réussir à passer du struct de parsing xml à un struct qui est envoyé dans ES.
Pour le passage je fais ça :
	if len(item.Date) > 0 {
fmt.Println("Date : "+item.Date)
addPublicationDate(&pub, item.Date)
}
La Fonction addPublicationDate c'est ça :
func addPublicationDate(p *Publication, date string) {
parts := strings.Split(date, "-")
pubDate := PublicationDate{}
pubDate.key = PublicationDateType
if len(parts) == 3 {
pubDate.date, _ = time.Parse("2006-01-02", date)
} else if len(parts) == 2 {
pubDate.date, _ = time.Parse("2006-01", date)
} else if len(parts) == 1 {
pubDate.date, _ = time.Parse("2006", date)
} else {
return
}
var pubDates []PublicationDate
pubDates = append(pubDates, pubDate)
p.Dates = pubDates
}
En gros c'est donc dans ce dernier code que je dois avoir un problème. J'arrive à faire de l'enregistrement de struct de struct dans ES, pour les auteurs par exemple, mais pour les dates, donc je dois bien merder à ce niveau là.
Cela doit venir du formatage des dates dans Go je pense.

Fabe, une idée ? :D
Guybrush 8342 Bob
yaugJe suis en train de développer un crawler de publications scientifiques en go pour enregistrer tout ça dans un Elasticsearch.
Je ne peux pas t'aider vu que je connais pas du tout Go (mais je vais lurker les infos ici :-D). Par contre, quelle était la motivation d'utiliser spécifiquement ce langage pour ce use-case ? C'est pas du tout du troll hein, mais de la curiosité : si je devais me mettre à Go, ce serait pour "quels cas" en particulier (sachant que je maîtrise Python) ?
yaug 1450 Spammeur
L'intérêt pour te mettre à go en connaissant bien python est minime je dirais, sauf peut être pour vraiment de la gestion de containers par exemple. Le point fort de go reste la gestion de la parallélisation.

Quand au choix de go, je voulais un langage bas niveau pour la partie crawling, que je ne connaisse pas, qui ne soit pas java (:D) et qui gère bien la parallélisation justement. Donc, bah autant choisir go. Y'a quelques trucs chiants mais au final j'ai déjà un truc presque fonctionnel et du coup j'améliore désormais, notamment en essayant de récupérer plus d'infos (d'où le topic), et aussi en croisant les sources d'infos, notamment avec CrossRef si j'ai un doi. Et sans doute aussi avec le nouvel outil d'opencitation.
Guybrush 8342 Bob
Ok ! ;-)

Coté performance, on se situe dans quelle catégorie avec Go ? Plutôt très efficace genre C/C++, efficace genre Rust/Java, ou peu efficace genre Python "out-of-the-box" (ou pas du tout efficace genre php ?).

Je rencontre parfois certains soucis bien spécifiques coté perfs avec Python (les cas où numpy n'est pas impliqué, ou Cython/Numba n'est pas appliquable/envisageable, et PyPy n'est pas encore assez "répandu" pour le déployer). Dans ce genre de cas, il ne me reste qu'à écrire les quelques lignes en C et l'interfacer avec Python (ce qui est super simple, fort heureusement :-D) mais j'aimerai un truc un peu plus... "convivial" que C. J'avais hésité à essayer Rust pour cette raison (mais je n'ai pas encore trouvé le temps) mais je sais que Go est très très bien supporté par Python, donc si les perfs sont au rendez-vous, ça pourrait être intéressant.
yaug 1450 Spammeur
Côté perf, c'est du compilé à mettre du côté de java voir un peu mieux (une idée, pas de preuve de mon côté). Donc c'est assez costaud oui.
Fabe 607 Geek
yaugCela doit venir du formatage des dates dans Go je pense.
Oui et non, mais tu vas pleurer si je te montre le problème :-D

La root cause est que dans ta struct PublicationDate, tes champs key et date ne sont pas exportés. En modifiant la struct ils apparaissent bien:
type PublicationDate struct {
Key string `json:"key"`
Date time.Time `json:"date"`
}
Date : 2018
{"id":"","title":"","type":"","abstract":"","source":"","language":"","created_at":"0001-01-01T00:00:00Z","keywords":null,"identifiers":null,"dates":[{"key":"lol","date":"2018-01-01T00:00:00Z"}]}
Par contre la logique n'est pas claire pour moi. Comme tu vois le marshaller sérialise le time dans un format "ISO", ce qui est relativement prévisible. Mais visiblement ton mapping ES s'attend à devoir indexer une date dans un des trois formats que tu as donné, je pense donc que ça va coincer car la transformation de la date serait faite une fois en Go, puis une fois par ES.

Je vois trois solutions:

* virer ton mapping custom et mapper ton champ sur le built-in basic_date_time dans ton index.
* garder ton mapping custom mais typer PublicationDate.Date en string plutôt qu'en time.Time et ne pas appliquer de transformation par rapport à ce que tu lis dans le XML
* garder ton mapping custom et le typage de PublicationDate.Date mais implémenter func (PublicationDate) MarshallJSON pour effectuer la transformation inverse au moment du passage du serializer (3 transformations du coup).

PS: À quand le Markdown sur le forum ? :-D
Fabe 607 Geek
Guybrushpeu efficace genre Python "out-of-the-box" (ou pas du tout efficace genre php ?).
Ce troll d'il y a dix ans vu que PHP défonce Python une main dans le dos en terme de perf :-D

Ce qui n'enlève rien aux autres qualités de Python ;-)


Ce message a été modifié 1 fois. Dernière modification : 15 juillet 2018 à 13:13 par Fabe.

yaug 1450 Spammeur
Boarf les trolls sur php je n'y fais plus attention. Pour être hype désormais faut troller sur javascript. :D

Fabe, bien vu la majuscule.. je viens de tester et désormais cela fonctionne/ Mais clairement, je rage !
Pour la date j'ai du faire sauter le formatage ES pour que cela fonctionne yeap. Dommage.
Guybrush 8342 Bob
FabeCe troll d'il y a dix ans vu que PHP défonce Python une main dans le dos en terme de perf :-D
Ouais mais ils comparent PHP avec Zen >= 3, mais ne disent rien sur l'interpréteur Python utilisé (je suppose du "bête" CPython). Pour ne pas fausser la comparaison, la comparaison aurait du être effectuée avec PyPy (qui, en moyenne, s'avère 7 fois plus rapide que Python, mais qui malheureusement ne supporte pas encore pleinement les extensions écrites dans d'autres langages (comme C par exemple), même si ça commence à être largement suffisant pour les bibliothèques scientifiques usuelles).

Mais ok, je suis d'accord que php ne mérite pas le "pas du tout efficace" indiqué plus haut :-D


Ce message a été modifié 2 fois. Dernière modification : 15 juillet 2018 à 13:48 par Guybrush.

Fabe 607 Geek
Si à l'occasion tu tombes sur des benchmark qui te semblent comparables, ça m'intéresse. C'est pas évident de rester à jour sur l'évolution de chaque techno et leur positionnement relatif.

Répondre

Vous devez être inscrit et identifié.