{"id":2537,"date":"2023-12-28T22:54:10","date_gmt":"2023-12-28T21:54:10","guid":{"rendered":"https:\/\/devportfolio.net\/wp-dev-blog\/?p=2537"},"modified":"2023-12-29T16:37:22","modified_gmt":"2023-12-29T15:37:22","slug":"talend-et-mongodb-une-connexion-performante-flexible-et-evolutive","status":"publish","type":"post","link":"https:\/\/devportfolio.net\/wp-dev-blog\/talend-et-mongodb-une-connexion-performante-flexible-et-evolutive\/","title":{"rendered":"Talend et MongoDB : Une Connexion Performante, Flexible et Evolutive"},"content":{"rendered":"\n<p>Lors d&rsquo;un r\u00e9cent projet de mise en place d&rsquo;un PIM (Product Information Management) visant \u00e0 centraliser une grande quantit\u00e9 de donn\u00e9es, l&rsquo;utilisation de MongoDB s&rsquo;est av\u00e9r\u00e9e n\u00e9cessaire. Pour r\u00e9pondre \u00e0 ce besoin, j&rsquo;ai adopt\u00e9 une approche particuli\u00e8re ax\u00e9e sur l&rsquo;\u00e9volutivit\u00e9, et les performances. Dans cette d\u00e9marche, j&rsquo;ai exploit\u00e9 les routines Java de Talend Integration Suite pour \u00e9tablir une connexion \u00e0 MongoDB sans n\u00e9cessiter la licence BigData. Les r\u00e9sultats ont \u00e9t\u00e9 positifs, et dans cet article, je partage en d\u00e9tail cette approche. Bien que je me concentre ici sur la lecture d&rsquo;une collection pour des raisons de simplicit\u00e9, il est essentiel de souligner que cette approche peut tout aussi bien \u00eatre \u00e9tendue \u00e0 l&rsquo;insertion, \u00e0 la mise \u00e0 jour des donn\u00e9es, ainsi qu&rsquo;\u00e0 l&rsquo;extraction sous forme de flux des modifications du journal d&rsquo;historisation (OpLog), une fonctionnalit\u00e9 native de MongoDB.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>T\u00e9l\u00e9charger MongoDB Java Drivers<\/strong><\/h2>\n\n\n\n<p>La premi\u00e8re \u00e9tape essentielle est de t\u00e9l\u00e9charger <a href=\"https:\/\/mongodb.github.io\/mongo-java-driver\/\">MongoDB Java Drivers<\/a> pour commencer \u00e0 utiliser MongoDB. <\/p>\n\n\n\n<p>Les librairies cit\u00e9es ci-dessous seront ajout\u00e9es comme d\u00e9pendances \u00e0 votre routine Talend. <\/p>\n\n\n\n<p>Assurez-vous de choisir les versions compatibles avec votre version de MongoDB (<em>Dans cet exemple, nous utilisons le pilote Java v4.5.1 pour se connecter \u00e0 MongoDB v5.0<\/em>).<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/mvnrepository.com\/artifact\/org.mongodb\/mongodb-driver-core\/4.5.0\">MongoDB Java Driver Core<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/mvnrepository.com\/artifact\/org.mongodb\/mongodb-driver-sync\/4.5.0\">MongoDB Java Driver Sync<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/mvnrepository.com\/artifact\/org.mongodb\/bson\/4.5.0\">BSON classes<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Cr\u00e9er une nouvelle routine <\/strong><\/h2>\n\n\n\n<p>Maintenant que nous avons t\u00e9l\u00e9charg\u00e9 les librairies Java, nous allons cr\u00e9er une routine Talend nomm\u00e9e <strong>MongoDBConnection<\/strong> pour encapsuler notre logique de connexion \u00e0 la base de donn\u00e9es.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">package routines;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport org.bson.Document;\nimport org.bson.conversions.Bson;\n\nimport com.mongodb.ConnectionString;\nimport com.mongodb.client.MongoClients;\nimport com.mongodb.client.MongoCursor;\nimport com.mongodb.client.MongoDatabase;\nimport com.mongodb.client.model.Aggregates;\n\n\/**\n * Classe permettant la connexion \u00e0 une base de donn\u00e9es MongoDB et l'ex\u00e9cution\n * d'op\u00e9rations.\n * \n * @author Votre Nom\n *\/\npublic class MongoDBConnection {\n\n    private final String databaseName;\n    private final String connectionString;\n    private boolean isProcessFinished = false;\n\n    private MongoCursor&lt;Document&gt; mongoCursor;\n\n    \/**\n     * Constructeur de la classe MongoDBConnection.\n     * \n     * @param connectionString L'URL de connexion \u00e0 MongoDB.\n     * @param databaseName     Le nom de la base de donn\u00e9es MongoDB.\n     *\/\n    public MongoDBConnection(String connectionString, String databaseName) {\n        this.connectionString = isEmpty(connectionString) ? \"mongodb:\/\/127.0.0.1:27017\" : connectionString;\n        this.databaseName = requireNonEmpty(databaseName, \"Database name cannot be null or empty.\");\n    }\n\n    \/**\n     * \u00c9tablit une connexion \u00e0 la base de donn\u00e9es MongoDB.\n     * \n     * @return La base de donn\u00e9es MongoDB connect\u00e9e.\n     * @throws IllegalArgumentException Si la connexion \u00e9choue.\n     *\/\n    public MongoDatabase connect() {\n        try {\n            return MongoClients.create(new ConnectionString(connectionString)).getDatabase(databaseName);\n        } catch (Exception ex) {\n            throw new IllegalArgumentException(ex.getMessage());\n        }\n    }\n\n    \/**\n     * Ex\u00e9cute une requ\u00eate sur une collection MongoDB avec des options de\n     * filtrage et de tri facultatives.\n     * \n     * @param collectionName Le nom de la collection \u00e0 interroger.\n     * @param queryString    La cha\u00eene de filtrage de la requ\u00eate.\n     * @param sortString      La cha\u00eene de tri de la requ\u00eate.\n     * @throws IllegalArgumentException Si le nom de la collection est nul ou vide.\n     *\/\n    public void queryCollection(String collectionName, String queryString, String sortString) {\n        if (isEmpty(collectionName)) {\n            throw new IllegalArgumentException(\"Collection name cannot be null or empty.\");\n        }\n\n        Bson filter = getAggregationOperatorFromString(queryString);\n\n        List&lt;Bson&gt; operators = (isEmpty(sortString))\n                ? Arrays.asList(Aggregates.match(filter))\n                : Arrays.asList(Aggregates.match(filter), Aggregates.sort(getAggregationOperatorFromString(sortString)));\n\n        mongoCursor = connect().getCollection(collectionName).aggregate(operators).iterator();\n    }\n\n    \/**\n     * Convertit une cha\u00eene en op\u00e9rateur d'agr\u00e9gation MongoDB (Bson Document).\n     * \n     * @param operator La cha\u00eene repr\u00e9sentant l'op\u00e9rateur.\n     * @return L'op\u00e9rateur d'agr\u00e9gation MongoDB sous forme de Document Bson.\n     *\/\n    public Document getAggregationOperatorFromString(String operator) {\n        if (isEmpty(operator)) {\n            return Document.parse(\"{}\");\n        }\n\n        return Document.parse(operator);\n    }\n\n    \/**\n     * R\u00e9cup\u00e8re le document suivant du curseur.\n     * \n     * @return Le document suivant ou null si le curseur est vide.\n     *\/\n    public Document getNextDocument() {\n        if (mongoCursor != null) {\n            Document next = mongoCursor.tryNext();\n            if (next != null) {\n                return next;\n            } else {\n                mongoCursor.close();\n                this.isProcessFinished = true;\n            }\n        } else {\n            this.isProcessFinished = true;\n        }\n        return null;\n    }\n\n    \/**\n     * R\u00e9cup\u00e8re le document suivant sous forme de cha\u00eene JSON.\n     * \n     * @return Le document suivant au format JSON ou null si le curseur est vide.\n     *\/\n    public String getNextDocumentToJSON() {\n        Document doc = getNextDocument();\n        return (doc != null) ? doc.toJson() : null;\n    }\n\n    \/**\n     * V\u00e9rifie si le processus est termin\u00e9.\n     * \n     * @return true si le processus est termin\u00e9, false sinon.\n     *\/\n    public boolean isProcessFinished() {\n        return this.isProcessFinished;\n    }\n\n    \/**\n     * V\u00e9rifie si la cha\u00eene est vide ou contient \"null\".\n     * \n     * @param s La cha\u00eene \u00e0 v\u00e9rifier.\n     * @return true si la cha\u00eene est vide ou contient \"null\", false sinon.\n     *\/\n    public static boolean isEmpty(String s) {\n        if (s == null) {\n            return true;\n        }\n        if (s.trim().isEmpty()) {\n            return true;\n        }\n        if (s.trim().equals(\"null\")) {\n            return true;\n        }\n        return false;\n    }\n\n    \/**\n     * Exige une valeur non vide, sinon l\u00e8ve une exception avec le message\n     * sp\u00e9cifi\u00e9.\n     * \n     * @param value   La valeur \u00e0 v\u00e9rifier.\n     * @param message Le message \u00e0 inclure dans l'exception.\n     * @return La valeur si elle n'est pas vide.\n     * @throws IllegalArgumentException Si la valeur est vide.\n     *\/\n    private static String requireNonEmpty(String value, String message) {\n        if (isEmpty(value)) {\n            throw new IllegalArgumentException(message);\n        }\n        return value;\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Ajouter les d\u00e9pendances \u00e0 la routine<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"998\" height=\"720\" src=\"https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_1.png\" alt=\"\" class=\"wp-image-2538\" srcset=\"https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_1.png 998w, https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_1-300x216.png 300w, https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_1-768x554.png 768w\" sizes=\"auto, (max-width: 998px) 100vw, 998px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Cr\u00e9er un nouveau job <\/strong><\/h2>\n\n\n\n<p>Cr\u00e9ez un nouveau job Talend pour tester la routine MongoDBConnection, que vous pouvez nommer <strong>job_Read_Mongo_Collection<\/strong>. Ajoutez deux composants, <strong>tJavaFlex<\/strong> et <strong>tLogRow<\/strong>, puis reliez-les en renommant le lien comme <strong>NEXT_DOCUMENT<\/strong>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"513\" height=\"288\" src=\"https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_2.png\" alt=\"\" class=\"wp-image-2540\" srcset=\"https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_2.png 513w, https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_2-300x168.png 300w\" sizes=\"auto, (max-width: 513px) 100vw, 513px\" \/><\/figure>\n\n\n\n<p>Adaptez le code suivant et modifiez la connexion et le nom de la base pass\u00e9s en param\u00e8tres du constructeur de <strong>MongoDBConnection<\/strong>.<\/p>\n\n\n\n<p>Modifiez \u00e9galement le nom de la collection et le filtre (optionnel) \u00e0 appliquer sur la collection.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"java\" class=\"language-java\">MongoDBConnection mongoConnection = new MongoDBConnection(\"mongodb:\/\/127.0.0.1:27017\", \"PIMSOG\");\nmongoConnection.queryCollection(\"H308\", \"{ EAN13: '3324976120027' }\", null);\n\nwhile (true) {\n  String sRecord = mongoConnection.getNextDocumentToJSON();\n\n  if (mongoConnection.isProcessFinished() == Boolean.TRUE) {\n\n    break;\n  } else {\n\n    \/\/ Flux de sortie\n    if (sRecord != null) {\n      NEXT_DOCUMENT.Record = sRecord.trim();\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"649\" src=\"https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_3-1024x649.png\" alt=\"\" class=\"wp-image-2541\" srcset=\"https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_3-1024x649.png 1024w, https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_3-300x190.png 300w, https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_3-768x487.png 768w, https:\/\/devportfolio.net\/wp-dev-blog\/wp-content\/uploads\/2023\/12\/Talend_MongoDB_3.png 1052w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>En conclusion, l&rsquo;int\u00e9gration de MongoDB dans Talend peut s&rsquo;av\u00e9rer \u00e0 la fois puissante et flexible. En adoptant une approche bas\u00e9e sur des routines Java personnalis\u00e9es, nous avons d\u00e9montr\u00e9 comment \u00e9tablir une connexion \u00e0 une base de donn\u00e9es MongoDB sans n\u00e9cessiter la licence BigData, offrant ainsi une solution \u00e9volutive et performante.<\/p>\n\n\n\n<p>La simplicit\u00e9 de l&rsquo;exemple pr\u00e9sent\u00e9 ici, se limitant \u00e0 la lecture d&rsquo;une collection MongoDB, ne refl\u00e8te qu&rsquo;une fraction des capacit\u00e9s offertes. J&rsquo;ai \u00e9tendu cette approche pour g\u00e9rer l&rsquo;insertion, la mise \u00e0 jour de donn\u00e9es, ainsi que l&rsquo;extraction du journal des modifications (OpLog) de MongoDB pour un mode delta.<\/p>\n\n\n\n<p>Cette approche procure une ma\u00eetrise totale de votre code, une \u00e9volutivit\u00e9 garantie et des par exp\u00e9rience des performances optimales. L&rsquo;int\u00e9gration de MongoDB avec Talend s&rsquo;\u00e9rige comme une solution robuste.<\/p>\n\n\n\n<p>J&rsquo;esp\u00e8re que cet article vous a fourni des insights utiles pour tirer parti de la synergie entre MongoDB et Talend, et je vous encourage \u00e0 explorer davantage cette approche pour r\u00e9pondre \u00e0 vos besoins sp\u00e9cifiques. N&rsquo;h\u00e9sitez pas \u00e0 partager vos exp\u00e9riences et \u00e0 poser des questions dans les commentaires. <\/p>\n\n\n\n<p><strong>Bonne int\u00e9gration !<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Lors d&rsquo;un r\u00e9cent projet de mise en place d&rsquo;un PIM (Product Information Management) visant \u00e0 centraliser une grande quantit\u00e9 de donn\u00e9es, l&rsquo;utilisation de MongoDB s&rsquo;est av\u00e9r\u00e9e n\u00e9cessaire. Pour r\u00e9pondre \u00e0 ce besoin, j&rsquo;ai adopt\u00e9 une approche particuli\u00e8re ax\u00e9e sur l&rsquo;\u00e9volutivit\u00e9, et les performances. Dans cette d\u00e9marche, j&rsquo;ai exploit\u00e9 les routines Java de Talend Integration Suite [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":2563,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13],"tags":[],"class_list":["post-2537","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-talend"],"_links":{"self":[{"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/posts\/2537","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/comments?post=2537"}],"version-history":[{"count":12,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/posts\/2537\/revisions"}],"predecessor-version":[{"id":2562,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/posts\/2537\/revisions\/2562"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/media\/2563"}],"wp:attachment":[{"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/media?parent=2537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/categories?post=2537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devportfolio.net\/wp-dev-blog\/wp-json\/wp\/v2\/tags?post=2537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}