Fermer

juillet 6, 2018

Créez des tableaux de bord personnalisés avec les fonctions MongoDB, Azure et sans serveur –


Cet article a été publié le Ahmad Awais . Merci de soutenir les partenaires qui rendent SitePoint possible.

TL; DR : Je construis un tableau de bord WordPress personnalisé pour un client d'entreprise qui est alimenté par React.js sur Node.js, avec MongoDB Atlas en tant que base de données.

Ce tableau de bord utilise plusieurs services Microsoft Azure, par exemple, les services cognitifs, Azure App Services et, en particulier, les fonctions Azure sans serveur. Dans cet article, vous apprendrez comment en construire un petit module et la raison derrière mon choix de pile, d'applications et de produits.


Un de mes clients d'entreprise qui possède une énorme entreprise de réseautage et de médias a un grand … échelle site WordPress mis en place. Récemment m'a consulté sur la possibilité de construire un tableau de bord WordPress personnalisé (basé sur WordPress REST API ) pour l'aider à prendre des décisions intelligentes via l'apprentissage automatique et l'intelligence artificielle. [19659003] Avec JavaScript dévorant le monde et WordPress s'adaptant au mouvement de créant le projet Gutenberg j'ai pensé à une architecture / pile où WordPress serait notre couche de contenu, un environnement familier éprouvé qui fait son travail bien avec un tableau de bord personnalisé construit avec JavaScript.

Lorsque vous êtes chargé de créer une application JavaScript moderne, vous vous trouvez dans un mélange de différents frameworks, outils et dev workflows. L'écosystème JavaScript a beaucoup évolué ces dernières années. Nous avons beaucoup, beaucoup de bonnes options disponibles aujourd'hui.

Ainsi, après avoir recherché mes options pour un peu, j'ai choisi d'employer React.js au-dessus de Node.js pour commencer à construire le tableau de bord personnalisé de WordPress. Alors que le projet est dans sa phase d'idéation pour le moment, je pense qu'il est important que je partage certains de nos objectifs ici pour définir le contexte derrière mon choix de la pile

Buts de tableau de bord WordPress personnalisés

entreprise où plus de 500 hôtels (dans trois pays différents) utilisent vos services pour alimenter leurs salles de conférence, réunions informatiques, et la gestion de la propriété en ligne comme les sites et les blogs. C'est ce que fait mon client.

La plupart de ce système est alimenté par une énorme instance WordPress multi-site qui gère tout pour les hôtels, sites Web, réservations en ligne, inscriptions, événements, billets, critiques et commentaires. Il existe également d'autres systèmes exécutant différents logiciels qui sont capables de produire du contenu via l'API REST.

Nous avons décidé de créer un tableau de bord WordPress personnalisé avec de nombreux objectifs en tête, mais j'en énumère quelques-uns qui sont lié à cet article particulier. Jetez un oeil à ce que j'ai construit jusqu'à présent, tout est basé sur des fonctions Azure sans serveur – qui sont assez impressionnantes.

 Un tableau de bord WordPress personnalisé avec MongoDB Atlas, Microsoft Azure et des fonctions sans serveur! reporting de données de niveau </h3>
<p> Le tableau de bord personnalisé va rapporter toutes les données de haut niveau, par ex. des choses comme des ventes en direct qui se déroulent dans tout le portefeuille de mon client (plus de 500 hôtels), des ventilations basées sur l'entité / le temps et la date. </p>
<p> Et comment chaque franchise fonctionne sur une base quotidienne, hebdomadaire ou mensuelle. Toutes ces données sont transmises à <a href= MongoDB Atlas .

⚡ Serverless Automation

La plupart des modules sont construits sur une architecture sans serveur – ce qui dans ce cas offre d'énormes avantages. Toutes les automatisations sont toujours en cours et le coût est payé au fur et à mesure que vous payez.

Une première estimation approximative rend cette solution 34% plus économique que d'avoir une VM de serveur fonctionnant tout le temps. Nous utilisons Azure Functions pour cette automatisation sans serveur.

Hub Hub IoT (Internet des objets)

Environ 200 responsables informatiques travaillent pour mon client qui ont des périphériques activés IoT qui alimentent les données dans plusieurs projets en ligne. Ce tableau de bord personnalisé inclut également ces données pour prendre de meilleures décisions et relier l'ensemble du concentrateur d'enregistrement, de gestion et de maintenance en un seul endroit.

Comme vous l'avez déjà deviné, ce projet utilise IoT Hub de Microsoft Azure pour connecter, surveiller et gérer tous les assets IoT.

? Machine Learning et Intelligence Artificielle

Nous utilisons beaucoup de différents services de Microsoft Azure pour rendre ce tableau de bord artificiellement intelligent Il y a un énorme jeu de données qui alimente le ML Studio qui nous aide à prédire différentes décisions comme la gestion de l'espace, les faibles tendances des inscriptions pour les événements informatiques et des questions telles que:

Bien que la partie Machine Learning dépasse la portée de cet article, je prévois toujours de me rapprocher de l'intelligence artificielle impressionnante que j'ai pu cuisiner via Azure s Services cognitifs .

? en direct et en temps réel

L'un des aspects les plus importants de ce tableau de bord personnalisé est qu'il est en direct et en temps réel. Ce qui signifie que j'ai besoin d'une base de données gérée capable de gérer cette quantité de données tout en restant hautement disponible.

Mais en même temps, c'est à des fins de gestion et sans impact sur les sites WordPress. C'est une décision cruciale de conception de système pour ce tableau de bord.

J'entends par là que nous pouvons faire toutes sortes d'expériences avec ce tableau de bord personnalisé, mais cela ne devrait pas avoir d'impact sur la base de données.

MongoDB & MongoDB Atlas

Pour ce tableau de bord WordPress personnalisé, j'utilise MongoDB Atlas en tant que DBaaS (base de données en tant que service). Et je ne pourrais pas être plus heureux. Quand j'ai partagé pour la première fois que j'utiliserais MongoDB, beaucoup de développeurs ont eu des inquiétudes.

 Mongodb

La plupart des questions demandaient pourquoi j'ajouterais un autre niveau de complexité en ajoutant encore une autre base de données au mélange. Pourquoi ne pas utiliser la base de données WordPress telle qu'elle est? Pour répondre à ces questions et plus, j'ai préparé une liste de raisons pour lesquelles j'utilise MongoDB Atlas .

♨ Je n'aime pas le SGBDR

Personnellement, je n'aime pas les bases de données relationnelles. La plupart du temps, pour moi, ils bloquent la construction d'applications. Je dois complètement sortir de l'application que je construis, penser à ma base de données à l'avenir et concevoir un bon schéma qui finit toujours par un mauvais exercice pour mon flux de travail dev. C'est au contraire contre-intuitif – au moins pour moi, c'est …

? HDD est bon marché – CPU / RAM n'est pas

Anciennes bases de données ont été principalement conçues pour économiser de l'espace disque, entre autres choses. Cela a conduit à une pléthore de problèmes tels que la normalisation, l'indexation, et rendu plus difficile la fragmentation, la mise à l'échelle automatique et la réplication.

De nos jours, l'espace disque est bon marché. D'autre part, CPU / RAM ne l'est pas, et vos coûts sysadmin peuvent grimper très rapidement si vous vous retrouvez avec un mauvais choix ici.

Comme vous vouliez créer un tableau de bord personnalisé, mais votre architecte système vous a coûté deux sysadmins avec comment ils ont choisi de concevoir votre système. De même, mon client voulait une solution gérée sans avoir à embaucher une équipe de développeurs IT / DevOps – au moins pour un tableau de bord personnalisé expérimental.

Pros Pros de MongoDB

  • Schema-less . Schéma flexible pour la victoire Je n'ai pas besoin de changer quoi que ce soit, mon flux de travail de développement d'applications habituel, en créant une application basée sur Node.js que je manipule avec des données de type JSON, je peux juste l'alimenter en MongoDB et cela fonctionne
  • . Crée des documents de la même manière que mon tableau de bord personnalisé. Les ventes, les vidéos, les discussions, les commentaires, les critiques, les inscriptions, etc. ont tous une représentation des données similaire sur le frontend et le backend – et même dans la base de données. Je gère des données tierces via un middleware. Cette cohérence se traduit par un code propre.
  • Facilité d'extension . Il met à l'échelle les lectures en utilisant des jeux de réplicas. Scales écrit en utilisant sharding (auto-équilibrage). Allumez juste une autre machine et vous partez. Plus important encore, au lieu de la mise à l'échelle verticale via RDBMS, MongoDB vous permet de mettre à l'échelle horizontalement avec différents niveaux de cohérence. C'est un gros plus. ➕
  • Coût . Dépend de quel RDBMS bien sûr, mais MongoDB est gratuit et peut fonctionner sur Linux, idéal pour fonctionner sur des kits de produits moins chers.

? Pourquoi MongoDB Atlas ?

Eh bien, maintenant que je sais que MongoDB est le bon choix de base de données, il y a tellement d'options différentes pour héberger votre base de données. Je peux m'auto-héberger sur ma machine Linux via DigitalOcean, utiliser un fournisseur de cloud comme AWS / Azure ou choisir un service DBaaS spécifique à MongoDB.

 Mongodb Atlas

Mais je veux une solution MongoDB rapide, sécurisée et gérée, que je puisse facilement adapter à la croissance du nombre de modules que nous attachons dans ce tableau de bord WordPress personnalisé. C'est MongoDB Atlas .

MongoDB Atlas est un service MongoDB hébergé dans le cloud conçu et géré par la même équipe qui construit la base de données. Et devinez quoi, je crois qu'ils suivent les meilleures pratiques opérationnelles puisque ce sont eux qui construisent MongoDB en premier lieu.

Je veux que ce tableau de bord personnalisé soit autogéré, sans serveur, et en utilisant MongoDB Atlas me sauve de se soucier des correctifs logiciels, des sauvegardes et de la configuration fiable de la configuration pour les nouvelles mises à jour de base de données. Encore un gros plus. ➕

De plus, le fait que MongoDB Atlas soit supporté cross-platform ainsi que cross-region et entre différents fournisseurs de cloud en fait un bien meilleur choix. Je pense que chaque Cluster est livré avec deux jeux de réplicas, prêts à l'échelle.

? MongoDB Compass

Maintenant que nous allons travailler avec MongoDB, ce serait génial d'avoir un outil pour explorer notre base de données, voir les changements, déboguer et ainsi de suite. À cet effet, MongoDB prend à nouveau la tête avec un produit appelé MongoDB Compass . Jetez un coup d'oeil.

 Mongodb Compass

Je vous suggère d'aller de l'avant et de télécharger MongoDB Compass . C'est littéralement le meilleur outil pour visualiser votre base de données MongoDB. Voici un ensemble de fonctionnalités:

  • Visualisez et explorez: Jetez un coup d'œil à votre base de données, découvrez comment les choses se présentent et visualisez même des choses comme des cartes / coordonnées.
  • Insérer, modifier et supprimer: Vous pouvez également effectuer des opérations CRUD pour votre DB directement à partir de la boussole MongoDB. Facilite les tests.
  • Déboguer et optimiser: Enfin, analysez vos données, déboguez-les et découvrez les problèmes de performance directement dans une interface graphique géniale pour votre base de données. Cet outil est un must si vous travaillez avec MongoDB.
  • Extensible: Et la meilleure partie est que vous pouvez créer vos propres plugins pour étendre MongoDB Compass. Voici la documentation sur construisant vos propres plugins de boussole .
  • Enterprise Flavor : MongoDB Compass vient en quelques saveurs: Communauté (libre), et Enterprise (sous licence) – la version d'entreprise est celle Cela vous permet de visualiser le schéma DB.

✅ Démarrer avec MongoDB Atlas

Commençons et construisons un module simple qui fait partie du tableau de bord WordPress personnalisé que je construis. Pour ce module, nous collectons toutes les données relatives aux ventes. Pour cela, nous avons besoin d'une instance de MongoDB, et bien sûr nous utilisons MongoDB Atlas ici.

Etape # 1: Aller à MongoDB Atlas →

Accéder à l'Atlas MongoDB site et enregistrer une instance MongoDB entièrement hébergée sur AWS, avec RAM partagée et 512 Mo de stockage. Cliquez sur le bouton Premiers pas

 Mongodb Atlas

Étape # 2: Inscrivez-vous à MongoDB Atlas →

Maintenant, allez-y inscrivez-vous avec votre adresse e-mail et remplissez les détails. Il est étonnant que vous puissiez vous inscrire et utiliser une instance DB hébergée MongoDB Atlas gratuite, et ils ne vous demandent même pas d'ajouter une carte de crédit pour cela.

 Mongodb Atlas Signup

Step # 3: Créer le cluster

Vous allez maintenant être redirigé vers une page contenant un tas d'informations sur le nouveau cluster MongoDB que vous êtes sur le point de créer. Je vous suggère de revoir ces informations et d'avancer en cliquant sur le bouton Créer un cluster en bas, comme dans la capture d'écran ci-dessous.

 Mongodb Atlas Créer un cluster

# 4: Créer le nom d'utilisateur et le mot de passe de la base de données

Cela prendra une minute et votre base de données sera créée. Une fois que cela se produit, rendez-vous sur les Sécurité > Utilisateurs MongoDB et cliquez sur le bouton + AJOUTER UN NOUVEL UTILISATEUR sur la droite, pour créer un nouvel utilisateur. base de données. Gardons tous les autres paramètres définis par défaut pour le bien de cet intro-article.

Je définis l'utilisateur / passe comme usermongo mais vous savez mieux.

 GIF pour Fonctions MongoDB Atlas, Microsoft Azure et sans serveur

Étape 5: Ajouter une adresse IP à la liste blanche pour l'accès

Pour pouvoir accéder à votre base de données Atlas MongoDB, vous devez configurer la liste blanche IP avec l'adresse IP de votre serveur. L'application est hébergée. L'authentification est au-delà de ce que je discute ici donc dans le but de cette démo, laissons tout le monde (évidemment une mauvaise pratique dans la production).

Donc, encore une fois, rendez-vous à la Sécurité > IP Whitelist et cliquez sur le bouton + ADD IP ADDRESS sur la droite, et enfin sur le bouton ALLOW ACCESS FROM ANYWHERE pour autoriser l'accès anonyme.

 GIF pour MongoDB Atlas, Microsoft Azure et les fonctions sans serveur

Étape 6: Connexion via MongoDB Compass

Maintenant que l'accès IP de notre DB et un utilisateur a été créé, nous pouvons récupérer la chaîne de connexion et l'utiliser pour se connecter à notre base de données avec notre application MongoDB Compass.

Passez à Connectez puis choisissez Connectez-vous à MongoDB Compass et téléchargez Compass si vous ne l'avez pas fait. Copiez la chaîne de connexion URI. Enfin, ouvrez Compass et il devrait être capable de détecter la chaîne de connexion dans votre presse-papiers, lui permettre de se connecter à votre base de données.

Et vous êtes configuré pour visualiser votre base de données, analyser ses performances et même exécuter des opérations CRUD complètes. Impressionnant!

 GIF pour MongoDB Atlas, Microsoft Azure et les fonctions sans serveur

Maintenant que nous avons créé un Atlas MongoDB et l'avons connecté avec MongoDB Compass, nous pouvons aller de l'avant et commencer à construire notre Node.js application

API REST WordPress – FTW!

Ce tableau de bord personnalisé basé sur WordPress interagit avec l'instance WordPress via l'API WordPress REST . Comme il s'agit d'une application Node.js, j'utilise une impressionnante bibliothèque appelée wpapi écrite par K Adam White . Il a également construit une démo Express application WordPress. C'est ce dont je me suis inspiré en construisant ce tableau de bord personnalisé, donc vous verrez beaucoup de choses ici.

? Routeur personnalisé WordPress Basé sur Express

Le routeur est configuré avec ] Express . Voici un gestionnaire d'erreur de base et un modèle de routeur pour utiliser WordPress avec express.

 'use strict';

var express = require ('express');
var routeur = express.Router ();
var siteInfoMiddleware = require ('../ middleware / site-info');

// Définir des informations de site globales sur tous les itinéraires
router.use (siteInfoMiddleware);

// Itinéraires publics
// =============

router.get ('/', require ('./ index'));
router.get ('/ page /: page', require ('./ index'));
router.get ('/: slug', require ('./ single'));
router.use ('/ tags /: tag', require ('./ tag'));
router.use ('/ categories /: category', require ('./ category'));

// Attrape 404 et passe au gestionnaire d'erreur.
router.use (fonction (req, res, next) {
    var err = new Erreur ('Non trouvé');
    err.status = 404;
    suivant (err);
});

// La gestion des erreurs
// ==============

// Le gestionnaire d'erreur de développement va imprimer stacktrace.
function developmentErrorRoute (err, req, res, next) {
    res.status (err.status || 500);
    res.render ('erreur', {
        message: err.message,
        erreur: err
    });
}

// Gestionnaire d'erreurs de production. Aucun stacktraces n'a fui vers l'utilisateur.
function friendlyErrorRoute (err, req, res, next) {
    res.status (err.status || 500);
    res.render ('erreur', {
        message: err.message,
        Erreur: {}
    });
}

// Configurer le comportement de gestion des erreurs
if (router.get ('env') === 'développement') {
    router.use (developmentErrorRoute);
} autre {
    router.use (friendlyErrorRoute);
}

module.exports = routeur;

Voir le code sur Gist

? Basic Express Based Implémentation

Je n'héberge pas tout cela sur WordPress, mais le plan initial était de faire exactement cela. Si vous voulez faire cela, vous voudriez construire l'index en interrogeant toutes les informations en utilisant l'utilitaire RSVP.hash pour plus de commodité et de parallélisme. Pour cela, voici ce que vous devriez faire.

 'use strict';

var wp = require ('../services/wp');
var contentService = require ('../services/content-service');
var pageNumbers = require ('../services/page-numbers');
var pageTitle = require ('../services/page-title');
var RSVP = require ('rsvp');

function getHomepage (req, res, next) {
  var pages = pageNumbers (req.params.page);

  RSVP.hash ({
    archiveBase: '',
    pages: pages,
    titre: pageTitle (),
    // Contenu de la page principale
    messages: wp.posts (). page (pages.current),
    barre latérale: contentService.getSidebarContent ()
  }). then (fonction (contexte) {
    if (req.params.page &&! context.posts.length) {
      // Pagination invalide: 404
      retour suivant ();
    }

    res.render ('index', contexte);
  }). catch (suivant);
}

module.exports = getHomepage;

Voir le code sur Gist .

? Authentification Cuite dans

Pour cette configuration, vous devrez également authentifier votre application Node.js en lui donnant les données d'authentification avec wpapi peut être traité comme ceci. Attention, ce n'est pas toujours une bonne pratique si vous n'utilisez pas les permissions correctes et les paramètres de variables d'environnement.

 var WP = require ('wordpress-rest-api');
var _ = require ('lodash');

var config = _.pick (require ('./config') .wordpress, [
  // Whitelist valid config keys
  'username',
  'password',
  'endpoint'
]);

var wp = nouveau WP (config);

module.exports = wp;

Voir le code sur Gist .

? Accumulation de contenu de site

Et enfin, vous êtes capable de consommer tout le contenu en créant un service de contenu qui gère l'extraction récursive:

  • les pages d'une collection paginée.
  • Les informations de votre site WordPress
  • Une liste alphabétique des catégories
  • Une catégorie spécifique (spécifiée par slug) du cache de contenu.
  • Une liste alphabétique de tags. [19659106] Une balise spécifique (spécifiée par slug) à partir du cache de contenu
  • Autre contenu requis pour avoir une certaine parité avec WP.

Le code pour ceci ressemble un peu à ceci.

 'use strict' ;

var wp = require ('./wp');
var cache = require ('./content-cache');
var _ = require ('lodash');
var RSVP = require ('rsvp');

/ **
 * Récupérer récursivement toutes les pages d'une collection paginée
 *
 * @param {Promise} request Une promesse à une réponse à une requête WP API
 * @returns {Array} Une promesse à un tableau de tous les enregistrements correspondants
 * /
function all (demande) {
  return request.then (fonction (réponse) {
    if (! response._paging ||! response._paging.next) {
      réponse de retour;
    }
    // Demande la page suivante et renvoie les deux réponses en une seule collection
    return RSVP.all ([
      response,
      all( response._paging.next )
    ]). then (function (responses) {
      return _.flatten (réponses);
    });
  });
}

function siteInfo (prop) {
  var siteInfoPromise = cache.get ('site-info');

  if (! siteInfoPromise) {
    // Instancie, demande et cache la promesse
    siteInfoPromise = wp.root ('/') .then (fonction (info) {
      retour d'informations;
    });
    cache.set ('site-info', siteInfoPromise);
  }

  // Renvoie la propriété demandée
  return siteInfoPromise.then (fonction (info) {
    retour prop? info [ prop ]: info;
  });
}

/ **
 * Obtenez une liste alphabétique des catégories
 *
 * Toutes les routes d'archives affichent une liste triée de catégories dans leur barre latérale.
 * Nous générons cette liste ici pour nous assurer que la logique de tri n'est pas dupliquée
 * à travers les routes.
 *
 * @method triéesCatégories
 * @return {Array} Un tableau d'objets de catégorie
 * /
function sortedCategories () {
  return all (wp.categories ()) .then (function (categories) {
    return _.chain (catégories)
      .sortBy ('limace')
      .valeur();
  });
}

function sortedCategoriesCached () {
  var categoriesPromise = cache.get ('triées-catégories');

  if (! categoriesPromise) {
    categoriesPromise = triéesCatégories ();
    cache.set ('sorted-categories', categoriesPromise);
  }

  return categoriesPromesse;
}

/ **
 * Obtenir une catégorie spécifique (spécifiée par slug) du cache de contenu
 *
 * L'API WP ne prend actuellement pas en charge les collections de termes de taxonomie de filtrage,
 * nous devons donc demander toutes les catégories et les filtrer si nous voulons obtenir
 * un terme individuel.
 *
 * Pour rendre cette requête plus efficace, elle utilise sortedCategoriesCached.
 *
 * @method categoryCached
 * @param {String} slug Le limace d'une catégorie
 * @return {Promise} Une promesse à la catégorie avec la limace fournie
 * /
fonction categoryCached (slug) {
  return sortedCategoriesCached (). then (function (categories) {
    return _.findWhere (categories, {
      limace: limace
    });
  });
}

/ **
 * Obtenir un tag spécifique (spécifié par slug) du cache de contenu
 *
 * L'API WP ne prend actuellement pas en charge les collections de termes de taxonomie de filtrage,
 * donc nous devons demander toutes les étiquettes et les filtrer si nous voulons obtenir un
 * terme individuel.
 *
 * Pour rendre cette requête plus efficace, elle utilise la promesse cachetée sortedTags.
 *
 * @method tagCached
 * @param {String} slug Le slug d'un tag
 * @return {Promise} Une promesse à l'étiquette avec la limace fournie
 * /
fonction tagCached (slug) {
  return sortedTagsCached (). then (function (tags) {
    return _.findWhere (balises, {
      limace: limace
    });
  });
}

/ **
 * Obtenez une liste alphabetisée des tags
 *
 * @method sortedTags
 * @return {Array} Un tableau d'objets tag
 * /
function sortedTags () {
  return all (wp.tags ()) .then (fonction (balises) {
    return _.chain (tags)
      .sortBy ('limace')
      .valeur();
  });
}

function sortedTagsCached () {
  var tagsPromise = cache.get ('tags triés');

  if (! tagsPromise) {
    tagsPromise = sortedTags ();
    cache.set ('sorted-tags', tagsPromise);
  }

  return tagsPromise;
}

function getSidebarContent () {
  return RSVP.hash ({
    catégories: triéesCatégoriesCachées (),
    Tags: triésTagsCachés ()
  });
}

module.exports = {
  // Effectue une recherche récursive dans une collection pour récupérer tous les éléments correspondants
  tout: tout,
  // Récupère (et met en cache) les informations de premier niveau sur un site, en retournant le
  // valeur correspondant à la clé fournie
  siteInfo: siteInfo,
  triéesCatégories: triéesCatégories,
  triéesCatégoriesSérie: triéesCatégoriesSérie,
  catégorieCached: categoryCached,
  tagCached: tagCached,
  triésTags: triésTags,
  triéTagsCaché: triéTagsCaché,
  getSidebarContent: getSidebarContent
}

Voir le code sur Gist

? Routes personnalisées et données de ventes

Enfin, j'ai cuisiné sur plusieurs routes personnalisées d'où je peux accéder à n'importe quel type de données liées aux ventes. Pour l'architecture particulière que j'ai en place, j'utilise de nouveau l'utilitaire RSVP.hash pour plus de commodité et de parallélisme. Cela fonctionne comme un charme.

 var WPAPI = require ('wpapi');
var RSVP = require ('rsvp');

// Utilisation de l'utilitaire RSVP.hash pour plus de commodité et de parallélisme
RSVP.hash ({
  categories: wp.categories (). slug ('it-services'),
  tags1: wp.tags (). slug ('nom-hôtel'),
  tags2: wp.tags (). slug ('événements de mars')
}). then (fonction (résultats) {
    // Combinaison et mappage des résultats .slug () dans des tableaux d'ID par taxonomie
    var tagIDs = results.tags1.concat (results.tags2)
        .map (fonction (balise) {return tag.id;});
    var categoryIDs = résultats.catégories
        .map (fonction (cat) {return cat.id;});
    return wp.posts ()
        .tags (tags)
        .catégories (catégories);
}). then (fonction (messages) {
    // Ces articles sont tous de la fiction, que ce soit du réalisme magique ou historique:
    console.log (messages);
});

Voir le code sur Gist .

Une fois que j'ai ces données, je les envoie à Paddle.com pour traitement avec la demande de commande achetée afin qu'elle puisse être ajoutée à notre instance MongoDB via des fonctions Azure sans serveur.

 // Enregistrement d'itinéraires personnalisés.
site.itSales = site.registerRoute ('ventes / v1', '/ resource / (? P  \ d +)');
site.itSales (). somePart (7); // => myplugin / v1 / resource / 7

// Paramètres de requête et filtrage des itinéraires personnalisés.
site.handler = site.registerRoute ('sales / v1', 'receipts / (? P )', {
    // La liste de tous ces paramètres assignera le built-in
    // méthode de chaînage qui gère le paramètre:
    params: [ 'before', 'after', 'author', 'parent', 'post' ]
});

// Donne des données personnalisées des acheteurs.
site.handler (). post (8) .author (92) .avant (dateObj) ... // Envoyé pour pagayer.

Voir le code sur Gist .

Cela peut sembler bizarre mais WordPress vous permet de configurer des types de post personnalisés et des taxonomies personnalisées, ce que j'utilise ici, le code ci-dessus, Cependant, ce n'est pas l'implémentation exacte mais une approche similaire à ce que j'ai utilisé via les catégories et les balises.

Ces données sont envoyées à Paddle, et elles sont fortement cachées afin que nos instances WordPress n'obtiennent aucune sorte de charge pendant que nous expérimentons. le tableau de bord personnalisé. J'ai aussi cuisiné dans un petit module d'actualisation des données qui récupère les données à la demande de l'instance WordPress de son choix.

Microsoft Azure & Azure Functions

En construisant ce tableau de bord WordPress personnalisé, je voulait s'assurer que chaque module de ce tableau de bord vivait sous la forme d'une application sans serveur avec plusieurs fonctions sans serveur. Cette décision était basée sur le fait que le coût de ce tableau de bord était le plus économique possible.

? Trois options

Trois grands fournisseurs de services de cloud sont présents. Ce sont Microsoft Azure Google Cloud Platform et Amazon Web Services . Chacun d'entre eux dispose de fonctions sans serveur, appelées respectivement fonctions Azure, GCP Cloud Functions et AWS Lambdas.

? Choisir Azure

Azure possède l'une des plus grandes architectures de nuages ​​et présences globales. 50 régions Azure, plus que n'importe quel fournisseur de cloud et après avoir testé chacun de ces trois, j'ai trouvé que les fonctions Azure avaient le meilleur temps de réponse aux Emirats Arabes Unis (puisque l'activité de mon client est basée sur les Emirats Arabes Unis). utilisez Azure ML Studio, AI Cognitive Services et Virtual Machines pour héberger des parties de ce projet, cela signifie qu'il est parfaitement logique d'utiliser les fonctions Azure pour l'architecture sans serveur.

Premiers pas avec les fonctions Azure

Commençons par Fonctions Azure Je vais vous guider dans le processus de création d'une simple fonction Azure sans serveur, qui sera déclenchée via des requêtes HTTP, et à l'intérieur, nous traiterons les informations sur les ventes qui nous sont envoyées par Paddle.com.

  1. Je construis une fonction Azure sans serveur basée sur JavaScript et plus particulièrement sur le code Node.js
  2. Cette fonction Azure sera déclenchée par une simple requête HTTP GET de notre 3rd solution de paiement de partie, par exemple, Paddle.com
  3. Dès qu'il y a une vente sur Paddle.com, il déclenchera un webhook qui contient des informations relatives à notre vente, quantité, article, gains, et En utilisant l'API REST WordPress, j'ai ajouté quelques données personnalisées liées à l'utilisateur qui a acheté le produit, comme l'ID de l'utilisateur dans WordPress DB, quel site WordPress avait cette vente, et méta-info de cet utilisateur.
  4. Lorsque la fonction Azure reçoit cette information GET demande, traite les informations, supprime ce dont j'ai besoin dans le cluster MongoDB Atlas et forme un objet JavaScript prêt à être enregistré dans la base de données.
  5. La fonction Azure se connecte ensuite à MongoDB Instance Atlas via un package npm appelé mongoose où après avoir connecté la base de données, je crée un modèle / schéma de base de données, puis ces données sont enregistrées dans MongoDB Atlas Cluster.
  6. se trouve là en attente de la prochaine vente, où mon client paie seulement le temps d'exécution et le montant des exécutions pour les fonctions Azure. ( 1 million sont gratuits chaque mois ?).

Maintenant, ce n'est qu'un résumé de haut niveau de ce qui se passe, il y a beaucoup de pas que j'ai sauté ici comme authentification qui est au-delà portée de cet article. Vous devriez toujours configurer l'authentification et la vérification pour garder les choses civiles et éviter tout excès.

Alors, allons-y et construisons cette chose.

Étape # 1: Configurer Microsoft Azure & VSCode

Je m'attends à ce que vous ayez le compte Azure mis en place de votre côté. Vous devrez vous abonner avec une carte de crédit car nous avons besoin de stockage pour héberger les fichiers Node.js, qui seront utilisés avec Azure Functions et vous devrez payer pour le stockage (vous obtiendrez probablement un crédit gratuit de 200 $ pour le premier mois , et même après que le coût est assez bas.)

Ainsi, allez-y et mettez en place ce qui suit:

  1. ✅ Configurez un compte Microsoft Azure avec une carte de crédit dans la facturation.
  2. ✅ Installez Visual Studio Code (Psst Je fais un cours sur VSCode ).
  3. ✅ Installez l'extension Azure Functions sur votre VSCode. 19659106] ? Pour activer le débogage local, installez le Azure Functions Core Tools .
  4. ? Créez un nouveau répertoire et ouvrez-le dans VSCode.

Si vous vous demandez quel thème et la police que j'utilise, c'est Shades of Purple ? – pour plus d'informations voir quel logiciel et matériel j'utilise . 9459006]

 7 VSCode Shades Of Purple

Étape # 2: Créer un nouveau projet d'application de fonction

Maintenant, créons un nouveau projet d'application de fonction. C'est vraiment facile avec VSCode. Tout ce que vous avez à faire est d'aller dans l'explorateur Azure Extension présent dans la barre d'activité. De là, accédez à l'onglet FONCTIONS et cliquez sur la première icône Créer un nouveau projet

Cela créera un projet de démonstration, avec les fichiers de base nécessaires pour démarrer et initialiser un dépôt Git pour toi. Je vais suivre les petites démos basées sur GIF pour vous simplifier la vie

 GIF pour MongoDB Atlas, Microsoft Azure et les fonctions sans serveur

Etape # 3: Créer une fonction Azure déclenchée par HTTP [19659014] Maintenant que nous avons créé un projet d'application de fonction, créons une fonction Azure sans serveur déclenchée par HTTP. Pour cela, accédez à l'explorateur d'extension Azure présent dans la barre d'activité. From there access the FUNCTIONS tab and click on the second icon Create Function.

For the sake of this demo, I am choosing to keep the authentication part simple, so I’m going to select anonymous access. The name of our Azure function is HttpTriggerJS so you can find a new directory created with that name inside your project. This should contain two files i.e. functions.json and index.js

⚡ A function is a primary concept in Azure Functions. You write code for a function in a language of your choice and save the code and configuration files in the same folder.

? The configuration is named function.jsonwhich contains JSON configuration data. It defines the function bindings and other configuration settings. The runtime uses this file to determine the events to monitor and how to pass data into and return data from function execution. Read more on this file in the official documentation here.

The following is an example function.json file that gets created.

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "type": "httpTrigger",
      "direction": "in",
      "name": "req"
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

View the code on Gist.

And then, there’s an index.js file which contains a basic code that you can use to test your Azure function. It receives a parameter name and prints it back to you or shows you an error asking for this parameter.

module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    if (req.query.name || (req.body && req.body.name)) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.query.name || req.body.name)
        }
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        }
    }
    context.done();
}

View the code on Gist.

GIF for MongoDB Atlas, Microsoft Azure, & Serverless Functions

Step #4: Deploy & Test Your Azure Function

Now that we have created an Azure function which can be triggered by a GET HTTP request, let’s go ahead and deploy it with VSCode and test it with the Postman API Explorer.

To deploy the function go to the Azure Extension explorer present in the activity bar. From there access the FUNCTIONS tab and click on the third icon Deploy to Function App.

This will ask you a bunch of questions about the name of your app, use anything unique. I used demo-wp-mdb-azure — VSCode then uses this to create a resource group, to group together your function-app related resources, its storage (used to save the files), and the created Azure function — finally responding back to us with a public URL.

I then went ahead to access this URL and it asked for the name param as per the code. When I sent the name param with the Postman app, it responded with Hello Ahmad Awais. ?

VSCode also asked me to update the function extension app versions to beta, and I chose yes — because that will help me use Node.js v8 for async/await.

Step #5: Create package.json and Install mongoose

Now that our Azure function is up and running, let’s create a package.json file in the root of our project and install mongoose. We’ll need this to connect and save data to our MongoDB Atlas Cluster.

Mongoose provides a straight-forward, schema-based solution to modeling your application data. It includes built-in typecasting, validation, query building, business logic hooks and more, out of the box. It’s pretty awesome. ?

GIF for MongoDB Atlas, Microsoft Azure, & Serverless Functions

Step #6: Add App Setting for MongoDB Connection

Now we are almost ready to start writing code for our application. But before doing that, we’ll need a connection string to be able to connect to our MongoDB Atlas Cluster (just like we did with MongoDB Compass). This connection string is private and you shouldn’t commit it to the git repo.

? This connection string belongs to the local.settings.json file in the project root. Let’s first download the settings, then add the MongodbAtlas setting with our connection string (get this string from the MongoDB Atlas dashboard) and upload the app settings.

To do this, go to the Azure Extension explorer present in the activity bar. From there access the FUNCTIONS tab and select your subscription, then your Azure function app, i.e., demo-wp-mdb-azure. Right click Application Settings and select Download remote settings… to download and Upload local settings… to upload the settings after adding the MongodbAtlas connection string to the settings.

Step #7: Update Node Version of Azure Function

In the code, I intend to use async/awaitwhich are not available on Node.js v6.5.0, which comes with the default version 1 of Azure functions. In step #4, VSCode asked me to update the runtime version of Azure function to beta and I did that. This enabled support for the latest Node.js versions on Azure functions.

So, let’s update the WEBSITE_NODE_DEFAULT_VERSION app setting in our local settings and update that to the remote settings.

GIF for MongoDB Atlas, Microsoft Azure, & Serverless Functions

Step #8: Create MongoDB Model/Schema

Before we save any data to our MongoDB Atlas Cluster, let’s create a modelSale.js file that will contain the model’s schema for what we intend to save in the database. It’s an extremely simple schema implementation, and I suggest you read up on what you can do here with mongoose and MongoDB.

This file is pretty much self-explanatory.

/**
 * Model: Sale
 */
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

// Sale Schema.
const saleSchema = new mongoose.Schema({
    sale_gross: Number,
    earnings: Number,
    currency: String,
    memberSince: Date,
    customerEmail: String,
    event_time: {
        type: Date,
        default: Date.now
    },
});


// Export the model.
module.exports = mongoose.model('Sale', saleSchema);

View the code on Gist.

Step #9: Code the ⚡ Azure Function with Node.js

Now let’s code our Azure function. I’m adding all the main code inside the index.js file for the purpose of this demo. I’m also going to use the context object as the first parameter, so make sure you read about that. Everything else is explained in the code snippet below.

So, this is just a demo code for this article. It does the following:

  • ✅ Gets the data from Paddle.com
  • ⚡ Connects to the MongoDB Atlas via connection string that we added in our Application Settings.
  • ? Uses the defined DB schema inside the test database where it creates a sales collection, including documents for our sales.
  • ⚙ Validates the data and creates a finalData object that gets saved in the MongoDB Atlas Cluster. Yay!
  • ? Finally, responds to the Paddle webhook with a 200 status code if all goes well, and does the context.done() dance.

Everything is pretty much explained with inline documentation.

/**
 * Azure Function: Sale.
 *
 * Gets data from Paddle.com (which in turn gets data
 * from WordPress) and processes the data, creates a
 * finalData object and saves it in MongoDB Atlas.
 *
 * @param context To pass data between function to / from runtime.
 * @param req HTTP Request sent to the Azure function by Paddle.
 */
module.exports = async function (context, req) {
    // Let's call it log.
    const log = context.log;

    // Log the entire request just for the demo.
    log('[RAN] RequestUri=%s', req.originalUrl);

    /**
     * Azure function Response.
     *
     * Processes the `req` request from Paddle.com
     * and saves the data to MongoDB Atlas while
     * responding the `res` response.
     */

    // Database interaction.
    const mongoose = require('mongoose');
    const DATABASE = process.env.MongodbAtlas;

    // Connect to our Database and handle any bad connections
    mongoose.connect(DATABASE);
    mongoose.Promise = global.Promise; // Tell Mongoose to use ES6 promises
    mongoose.connection.on('error', (err) => {
        context.log(`ERROR→ ${err.message}`);
    });

    // Sale Schema.
    require('./modelSale');
    const Sale = mongoose.model('Sale');

    // Create a Response.
    if (req.query.customFieldName) { // Simple authentication for the purpose of demo.

        // Build the data we need.
        const sale_gross = req.query.p_sale_gross || '0';
        const earnings = JSON.parse(req.query.p_earnings)['16413'] || '0'
        const currency = req.query.p_currency || 'USD';
        const memberSince = req.query.memberSince || new Date();
        const customerEmail = req.query.customerEmail || '';
        const event_time = new Date();

        log('[OUTPUT]—— sale_gross: ' + sale_gross);
        log('[OUTPUT]—— earnings: ' + earnings);
        log('[OUTPUT]—— currency: ' + currency);

        const finalData = {
            sale_gross: sale_gross,
            earnings: earnings,
            currency: currency,
            memberSince: memberSince,
            customerEmail: customerEmail,
            event_time: event_time,
        }

        // Save to db.
        const sale = await (new Sale(finalData)).save();
        log("[OUTPUT]—— SALE SAVED: ", sale);

        // Respond with 200.
        context.res = {
            status: 200,
            body: "Thank You for the payment! " + (req.query.customFieldName || req.body.customFieldName)
        }
    } else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        }
    }


    // Informs the runtime that your code has finished. You must call context.done, or else the runtime never knows that your function is complete, and the execution will time out.
    // @link: https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-node#contextdone-method
    context.done();
}

View the code on Gist.

Step #10: Re-deploy the Azure Function

Now let’s re-deploy the Azure function. For that, go to the Azure Extension explorer present in the activity bar. From there access the FUNCTIONS tab and click on the third Deploy to Function App icon.

GIF for MongoDB Atlas, Microsoft Azure, & Serverless Functions

Step #11: Test Azure Function via Paddle’s Webhook

Looks like we’re pretty much done. All that’s left is to test our Azure function by triggering a dummy webhook via Paddle.com. Let’s do that. Also, when things do work, let’s explore how our data looks in the MongoDB Compass.

Wow, humph! That was a lot. Glad it worked. ?

? So, What Just Happened?!

Prepare yourself for a mouthful. I created a small part of the Sales module in the custom WordPress Dashboard app that I am building. I used MongoDB Atlas and Compass, then created a Microsoft Azure Function via Function App with VSCode, deployed the app with an env secret as the application string with the MongoDB connection string, updated the Node.js version and triggered the function via a dummy webhook from Paddle.com (like it will trigger when a sale happens) to send data (from Paddle + WordPress) to our Azure function and from there to MongoDB Atlas. And it worked, haha!

Machine Learning & Artificial Intelligence

Machine learning and artificial intelligence are always a mesmerizing topic in the world of software technology but we don’t talk a lot about that in the context of WordPress or in the WP community.

I set to change that by adding a few small improvements to a select few WordPress sites for my client and have every intention of exploring the same with this custom WordPress dashboard.

I have discussed this topic before and shared what I am working on, take a look at this small artificial intelligence plugin I am building for WordPress, and integrating it with different Azure Cognitive Services.

I explained this in a video in another post that you can find here: Building a WordPress Artificial Intelligence Plugin →.

I’ve accomplished similar results in this dashboard with the wpapi package. First I upload the image to cognitive services and then on a confident response, I send it to WordPress to be uploaded via WordPress REST API, with an image description that gets generated by Computer Vision AI.

/**
 * Get Image Alt Recognition with Computer Vision
 * using Azure Cognitive Services.
 */
var WPAPI = require('wpapi');
var wp = new WPAPI({
    endpoint: 'http://src.wordpress-develop.dev/wp-json'
});

/**
 * Handle Image Alt Generation.
 */
function processImage() {
    // **********************************************
    // *** Update or verify the following values. ***
    // **********************************************

    // Replace  with your valid subscription key.
    var subscriptionKey = "";

    // You must use the same region in your REST call as you used to get your
    // subscription keys. For example, if you got your subscription keys from
    // westus, replace "westcentralus" in the URI below with "westus".
    //
    // Free trial subscription keys are generated in the westcentralus region.
    // If you use a free trial subscription key, you shouldn't need to change
    // this region.
    var uriBase =
        "https://westcentralus.api.cognitive.microsoft.com/vision/v2.0/analyze";

    // Request parameters.
    var params = {
        "visualFeatures": "Categories,Description,Color",
        "details": "",
        "language": "en",
    }

    // Display the image.
    var sourceImageUrl = document.getElementById("inputImage").value;
    document.querySelector("#sourceImage").src = sourceImageUrl;

    // Make the REST API call.
    $.ajax({
            url: uriBase + "?" + $.param(params),

            // Request headers.
            beforeSend: function (xhrObj) {
                xhrObj.setRequestHeader("Content-Type", "application/json");
                xhrObj.setRequestHeader(
                    "Ocp-Apim-Subscription-Key", subscriptionKey);
            },

            type: "POST",

            // Request body.
            data: '{"url": ' + '"' + sourceImageUrl + '"}',
        })

        .done(function (data) {
            // Show formatted JSON on webpage.
            $("#responseTextArea").val(JSON.stringify(data, null, 2));

            // Extract and display the caption and confidence from the first caption in the description object.
            if (data.description && data.description.captions) {
                var caption = data.description.captions[0];

                if (caption.text && caption.confidence >= 0.5) {
                    const imgDescription = caption.text;

                    // ⬆ Upload to WordPress.
                    wp.media()
                        // Specify a path to the file you want to upload, or a Buffer
                        .file(sourceImageUrl)
                        .create({
                            title: imgDescription,
                            alt_text: imgDescription,
                            caption: imgDescription,
                            description: imgDescription
                        })
                        .then(function (response) {
                            // Your media is now uploaded: let's associate it with a post
                            var newImageId = response.id;
                            return wp.media().id(newImageId).update({
                                post: associatedPostId
                            });
                        })
                        .then(function (response) {
                            console.log('Media ID #' + response.id);
                            console.log('is now associated with Post ID #' + response.post);
                        });
                }
            }
        })

        .fail(function (jqXHR, textStatus, errorThrown) {
            // Display error message.
            var errorString = (errorThrown === "") ? "Error. " :
                errorThrown + " (" + jqXHR.status + "): ";
            errorString += (jqXHR.responseText === "") ? "" :
                jQuery.parseJSON(jqXHR.responseText).message;
            alert(errorString);
        });
}

View the code on Gist.

? Content Moderation Automation

One of the ideas we have is to take AI/ML from Azure to use as a content moderation platformwhich offers a built-in human-in-the-loop + machine learning to help moderate images, text, and videos. It’s a work in progress but it’s something really interesting that you should definitely take a look at.

Content Moderator Block Diagram

? WordPress Grammar (Nazi) Intelligence

Y’all have a habit of typing the same typos over and over again. I do that all the time. The coolest thing ever is when search engines like Bing and Google can spell check and proofread the search query for you.

Imagine if WordPress had that?! So, I got to work and ended up cooking the same functionality in the WordPress admin area for when you type a typo in your post title (or more than one typos for all I care!).

WordPress AI Auto title correction proof reading and spell check suggestions

I was so excited that I couldn’t contain myself, so there’s me in the left bottom corner. All happy and surprised! ??????☝??

It’s Your Turn Now!

I really hope that you enjoyed this potential integration between all these modern JavaScript frameworks, AI/ML products, and serverless functions.

This project is a lot of fun. I think if you give this tech-stack a shot you can have this crazy amount of fun as well. So, I’m leaving it up to you to try MongoDB Atlasin the context of WordPress — and maybe attach all that to a bunch of serverless functions.






Source link