您的位置:首页 > 数据库 > Mongodb

erui _ eruie 003使用MongoDB,Azure和无服务器功能构建自定义仪表板

2020-05-06 04:37 1026 查看

本文最初发表于艾哈迈德·阿威斯(Ahmad Awais)。 感谢您支持使SitePoint成为可能的合作伙伴。

我的一个拥有庞大的网络和媒体公司的企业客户中,有一个大规模的WordPress网站已建立。 他最近咨询我关于构建自定义WordPress仪表板的可能性(基于WordPress REST API)-帮助他通过机器学习和人工智能做出明智的业务决策。

随着JavaScript吞噬了整个世界,WordPress逐渐适应了这一趋势创建古腾堡项目,我想到了一个架构/堆栈,其中WordPress将成为我们的内容层,这是一个经过考验的熟悉的环境,可以通过使用JavaScript构建的自定义仪表板很好地发挥作用。

以及他的每个专营权每天,每周,每月的表现如何。 所有这些数据都被馈送到MongoDB地图集。 以后再说。

初步估计,此解决方案比始终运行服务器VM的经济性高34%。 我们正在使用Azure功能对于这种无服务器自动化。

您可能已经猜到了,该项目利用了物联网中心从Microsoft Azure连接,监视和管理所有IoT资产。

有一个庞大的数据集ML Studio稍后可以帮助我们预测不同的决策,例如空间管理,IT事件的低注册趋势以及诸如此类问题发生的时间和原因等问题。

尽管“机器学习”部分不在本文讨论范围之内,但我仍计划使用一些我已经能够通过Azure的应用程序制作的超棒人工智能技术作为基础认知服务。

对于此自定义WordPress仪表板,我正在使用MongoDB地图集作为DBaaS(数据库即服务)。 而且我再也不能快乐了。 当我第一次分享我将使用MongoDB时,许多开发人员都对此感到担忧。

大部分问题问为什么我要通过添加另一个数据库来增加另一层复杂性。 为什么不按原样使用WordPress数据库? 为了回答这些问题以及更多问题,我准备了为什么要使用的原因列表MongoDB地图集。

  • 无架构。 获胜的灵活模式。 我不需要更改任何东西,我的常规应用程序开发工作流程,创建了一个我要处理的基于Node.js的应用程序,并使用JSON类型数据,我可以将其输入到MongoDB中并且可以正常工作。工作流一致性。 以表示我的自定义仪表板的方式创建文档。 销售,视频,对话,评论,评论,注册等在前端和后端(甚至在数据库中)都具有相似的数据表示。 我通过中间件管理第三者数据。这种一致性转化为干净的代码。易于横向扩展。 它通过使用副本集扩展读取。 通过使用分片(自动平衡)缩放写入。 只需启动另一台机器,然后您就可以离开。 最重要的是,除了通过RDBMS进行垂直扩展外,MongoDB还允许您以不同的一致性级别进行水平扩展。 这是一大优势。 ➕成本。 当然取决于哪个RDBMS,但是MongoDB是免费的,可以在Linux上运行,非常适合在便宜的商品套件上运行。

🍃为什么MongoDB地图集?

但是我想要一个快速,安全和托管的MongoDB解决方案,我可以随我们在此自定义WordPress仪表板中附加的模块数量的增加轻松地进行扩展。 那是MongoDB地图集。

MongoDB地图集是由云托管的MongoDB服务,由构建数据库的同一团队设计和运行。 猜猜是什么,我相信他们遵循最佳的操作实践,因为他们是首先构建MongoDB的人。

另外,支持MongoDB Atlas的事实跨平台以及跨区域而且跨不同的云提供商,这使其成为更好的选择。 我认为每个集群都有两个副本集,可以扩展。

现在,我们将与MongoDB一起工作,拥有一个可用来浏览数据库,查看更改,进行调试等工作的工具真是太好了。 为此,MongoDB再次率先推出了一款名为MongoDB指南针。 看一看。

我建议您继续下载MongoDB指南针。 实际上,这是可视化MongoDB数据库的最佳工具。 这是一组功能:

  • 可视化和探索:看一下数据库,了解事物的外观,甚至可视化诸如地图/坐标之类的东西。插入,修改和删除:您还可以直接从MongoDB指南针对数据库执行CRUD操作。 使测试更加容易。调试和优化:最后,对数据进行分析,调试,甚至在数据库的出色GUI内查找性能问题。 如果您使用MongoDB,则此工具是必备工具。可扩展:最好的部分是您可以构建自己的插件来扩展MongoDB Compass。 这是有关的文档构建自己的Compass插件。Enterprise Flavor: MongoDB Compass comes in a few flavors: Community (Free), and Enterprise (Licensed) — the Enterprise version is the one that lets you visualize DB schema。

步骤1:转到MongoDB地图集→

转到MongoDB地图集站点并注册AWS上托管的完全免费的MongoDB实例,该实例具有共享RAM和512 MB存储。 点击免费入门按钮。

步骤2:在进行注册MongoDB地图集→

现在,您将被重定向到一个页面,其中包含有关将要创建的新MongoDB集群的大量信息。 建议您查看此信息,然后点击创建集群底部的按钮,如下面的屏幕截图所示。

这将需要一分钟,您的数据库将被创建。 一旦发生这种情况,请前往安全 > MongoDB用户然后点击+添加新用户单击右侧的按钮,为您的数据库创建一个新用户。 为了介绍本文,让我们将所有其他设置保持为默认设置。

I’m setting the user/pass as

usermongo
but you know better.

因此,再次前往安全 > IP白名单然后点击+添加IP地址右边的按钮,最后允许从任何地方访问按钮以允许匿名访问。

去连接然后选择连接 with MongoDB Compass and download Compass if you haven’t. Copy the URI 连接ion String. Finally, open Compass and it should be able to detect the connection string in your clipboard, allow it to connect to your database.

This WordPress based Node.js custom dashboard interacts with the WordPress instance via the WordPress REST API. Since this is a Node.js app, I am using an awesome library called

wpapi
written by K Adam White. He has also built a demo Express based WordPress app. That’s what I got inspired by while building this custom dashboard, so you’ll see a lot of it here.

on基于的WordPress自定义路由器表达

路由器设置有表达。 这是将WordPress与express结合使用的基本错误处理程序和路由器模板。

'use strict';

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

// Set global site info on all routes
router.use(siteInfoMiddleware);

// Public Routes
// =============

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'));

// Catch 404 and forward to error handler.
router.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// Error Handling
// ==============

// Development error handler will print stacktrace.
function developmentErrorRoute(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
}

// Production error handler. No stacktraces leaked to user.
function friendlyErrorRoute(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
}

// Configure error-handling behavior
if (router.get('env') === 'development') {
router.use(developmentErrorRoute);
} else {
router.use(friendlyErrorRoute);
}

module.exports = router;
查看以下代码要旨。

I am not hosting this entire thing on WordPress, but the initial plan was to do just that. If you want to go do that, you’d wanna build the index by querying all the info using the

RSVP.hash
utility for convenience and parallelism. For that here’s what you should do.

'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,
title: pageTitle(),
// Primary page content
posts: wp.posts().page( pages.current ),
sidebar: contentService.getSidebarContent()
}).then(function( context ) {
if ( req.params.page && ! context.posts.length ) {
// Invalid pagination: 404
return next();
}

res.render( 'index', context );
}).catch( next );
}

module.exports = getHomepage;

查看以下代码要旨。

For this setup, you’ll also need to authenticate your Node.js app by giving it the authentication data, which along with

wpapi
can be processed like this. Beware this is not always a best practice if you don’t use correct permissions and environment variables settings.

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

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

var wp = new WP( config );

module.exports = wp;

查看以下代码要旨。

  • 分页集合的所有页面。您的WordPress网站的信息。按字母顺序排列的类别列表。内容缓存中的特定类别(由slug指定)。标签的字母顺序列表。内容缓存中的特定标签(由slug指定)与WP具有某些功能相等的其他内容。

'use strict';

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

/**
* Recursively fetch all pages of a paged collection
*
* @param {Promise} request A promise to a WP API request's response
* @returns {Array} A promise to an array of all matching records
*/
function all( request ) {
return request.then(function( response ) {
if ( ! response._paging || ! response._paging.next ) {
return response;
}
// Request the next page and return both responses as one collection
return RSVP.all([
response,
all( response._paging.next )
]).then(function( responses ) {
return _.flatten( responses );
});
});
}

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

if ( ! siteInfoPromise ) {
// Instantiate, request and cache the promise
siteInfoPromise = wp.root( '/' ).then(function( info ) {
return info;
});
cache.set( 'site-info', siteInfoPromise );
}

// Return the requested property
return siteInfoPromise.then(function( info ) {
return prop ? info[ prop ] : info;
});
}

/**
* Get an alphabetized list of categories
*
* All archive routes display a sorted list of categories in their sidebar.
* We generate that list here to ensure the sorting logic isn't duplicated
* across routes.
*
* @method sortedCategories
* @return {Array} An array of category objects
*/
function sortedCategories() {
return all( wp.categories() ).then(function( categories ) {
return _.chain( categories )
.sortBy( 'slug' )
.value();
});
}

function sortedCategoriesCached() {
var categoriesPromise = cache.get( 'sorted-categories' );

if ( ! categoriesPromise ) {
categoriesPromise = sortedCategories();
cache.set( 'sorted-categories', categoriesPromise );
}

return categoriesPromise;
}

/**
* Get a specific category (specified by slug) from the content cache
*
* The WP API doesn't currently support filtering taxonomy term collections,
* so we have to request all categories and filter them down if we want to get
* an individual term.
*
* To make this request more efficient, it uses sortedCategoriesCached.
*
* @method categoryCached
* @param {String} slug The slug of a category
* @return {Promise} A promise to the category with the provided slug
*/
function categoryCached( slug ) {
return sortedCategoriesCached().then(function( categories ) {
return _.findWhere( categories, {
slug: slug
});
});
}

/**
* Get a specific tag (specified by slug) from the content cache
*
* The WP API doesn't currently support filtering taxonomy term collections,
* so we have to request all tags and filter them down if we want to get an
* individual term.
*
* To make this request more efficient, it uses the cached sortedTags promise.
*
* @method tagCached
* @param {String} slug The slug of a tag
* @return {Promise} A promise to the tag with the provided slug
*/
function tagCached( slug ) {
return sortedTagsCached().then(function( tags ) {
return _.findWhere( tags, {
slug: slug
});
});
}

/**
* Get an alphabetized list of tags
*
* @method sortedTags
* @return {Array} An array of tag objects
*/
function sortedTags() {
return all( wp.tags() ).then(function( tags ) {
return _.chain( tags )
.sortBy( 'slug' )
.value();
});
}

function sortedTagsCached() {
var tagsPromise = cache.get( 'sorted-tags' );

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

return tagsPromise;
}

function getSidebarContent() {
return RSVP.hash({
categories: sortedCategoriesCached(),
tags: sortedTagsCached()
});
}

module.exports = {
// Recursively page through a collection to retrieve all matching items
all: all,
// Get (and cache) the top-level information about a site, returning the
// value corresponding to the provided key
siteInfo: siteInfo,
sortedCategories: sortedCategories,
sortedCategoriesCached: sortedCategoriesCached,
categoryCached: categoryCached,
tagCached: tagCached,
sortedTags: sortedTags,
sortedTagsCached: sortedTagsCached,
getSidebarContent: getSidebarContent
};

查看以下代码要旨。

Finally, I have cooked in quite a few custom routes from where I can attain any kind of sales related data. For the particular architecture I have in place, I’m again using the

RSVP.hash
utility for convenience and parallelism. It works like a charm.

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

// Using the RSVP.hash utility for convenience and parallelism
RSVP.hash({
categories: wp.categories().slug( 'it-services' ),
tags1: wp.tags().slug('hotel-name'),
tags2: wp.tags().slug('march-events')
}).then(function( results ) {
// Combine & map .slug() results into arrays of IDs by taxonomy
var tagIDs = results.tags1.concat( results.tags2 )
.map(function( tag ) { return tag.id; });
var categoryIDs = results.categories
.map(function( cat ) { return cat.id; });
return wp.posts()
.tags( tags )
.categories( categories );
}).then(function( posts ) {
// These posts are all fiction, either magical realism or historical:
console.log( posts );
});

查看以下代码要旨。

// Registering custom routes.
site.itSales = site.registerRoute( 'sales/v1', '/resource/(?P<some_part>\\d+)' );
site.itSales().somePart( 7 ); // => myplugin/v1/resource/7

// Query Parameters & Filtering Custom Routes.
site.handler = site.registerRoute( 'sales/v1', 'receipts/(?P<id>)', {
// Listing any of these parameters will assign the built-in
// chaining method that handles the parameter:
params: [ 'before', 'after', 'author', 'parent', 'post' ]
});

// Yields from the custom data of buyers.
site.handler().post( 8 ).author( 92 ).before( dateObj )... // Sent to paddle.
查看以下代码要旨。

This data gets sent Paddle, and it’s heavily cached so that our WordPress instances do not get any sort of load while we experiment with the custom dashboard. I’ve also cooked in a small

data-refresh
module which fetches the data on demand from the WordPress instance of choice.

目前有三个主要的云服务提供商。 这些是微软Azure,Google Cloud Platform,and 亚马逊网络服务. Each of these has serverless functions available,respectively called Azure functions,GCP Cloud Functions,and AWS Lambdas.

  1. I am building a serverless Azure function which is based on JavaScript and specifically Node.js code.
  2. This Azure function will get triggered by a simple
    GET
    HTTP request from our 3rd party payment solution, i.e., Paddle.com.
  3. As soon as there’s a sale on Paddle.com, it will trigger a webhook that contains info related to our sale, quantity, item, earnings, and some member-related data that WordPress sent to Paddle.
  4. Using the WordPress REST API, I have added some custom data related to the user who purchased the product, like user’s ID in WordPress DB, which WordPress site had this sale, and that user’s meta info.
  5. When the Azure function receives this
    GET
    request, it processes the info, takes out what I need to keep in the MongoDB Atlas Cluster and forms a JavaScript object ready to be saved in the DB.
  6. The Azure function then connects to the MongoDB Atlas instance via an npm package called mongoose, where after connecting the database, I create a DB Model/Schema, and then this data is saved to the MongoDB Atlas Cluster.
  7. After which Azure function kind of sits there waiting for next sale to happen, where my client only pays for the execution time and amount of executions for Azure functions. (1 million of which are free every month 😮).

我希望你有蔚蓝 account set up on your end. You’ll need to subscribe with a credit card since we need storage for hosting the Node.js files, which will be used with 蔚蓝 Functions and you have to pay for storage (you’ll probably get a free $200 credit for the first month, and even after that the cost is quite low).

  1. ✅设置一个微软Azure帐单中使用信用卡付款的帐户。✅安装Visual Studio程式码(抱歉,我正在VSCode课程)。✅安装the Azure Functions扩展在您的VSCode上。💡要启用本地调试,请安装Azure Functions核心工具。🗂 Create a new directory and open it up in VSCode。

如果您想知道我使用的是哪种主题和字体,紫色阴影💜—有关更多信息,请参阅哪个我使用的软件和硬件。

Now let’s create a new function app project. This is really easy with VSCode. All you have to do is go to the Azure Extension explorer present in the activity bar. From there access

FUNCTIONS
tab and click on the first
Create New Project
icon.

Now that we have created a function app project, let’s create an HTTP-triggered serverless 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 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功能 is a primary concept in Azure Functions. You write code for a 功能 in a language of your choice and save the code and configuration files in the same folder.

🛠 The configuration is named

function.json
, which 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"
}
]
}

查看以下代码要旨。

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();
};

查看以下代码要旨。

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
. 👍

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.

💯 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.

In the code, I intend to use

async
/
await
, which 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.

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.

/**
* 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);
查看以下代码要旨。

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.

  • ✅ 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.

/**
* 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();
};
查看以下代码要旨。

现在,让我们重新部署Azure功能。 为此,请转到活动栏中的Azure扩展资源管理器。 从那里访问功能标签,然后单击第三个部署到功能应用图标。

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!

我在另一篇视频的视频中对此进行了解释,您可以在此处找到:构建WordPress人工智能插件→。

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 <Subscription Key> with your valid subscription key.
var subscriptionKey = "<Subscription Key>";

// 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);
});
};

查看以下代码要旨。

我们的想法之一是将Azure的AI / ML用作内容审核平台,它提供了内置的“人在环环相扣+机器学习”功能,可帮助调节图像,文本和视频。 这是一项正在进行的工作,但确实值得您关注一下。

我非常激动,无法抑制自己,所以在左下角有我。所有人高兴和惊讶!🙌👐👏👊💪🎶☝😌🎧

这个项目很有趣。 我认为,如果您给这个技术栈一个机会,那么您也可以拥有如此疯狂的乐趣。 所以,我留给您尝试MongoDB地图集,在WordPress的背景下–也许将所有这些附加到一堆无服务器功能上。

from: https://www.sitepoint.com//build-custom-dashboards-with-mongodb-azure-serverless-functions/

dangzhuang7815 原创文章 0获赞 0访问量 322 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐