将Elasticsearch与Silex集成

tech2022-09-05  103

In the previous article I started exploring the integration between Drupal 7 and the Elasticsearch engine. The goal was to see how we can combine these open source technologies to achieve a high performance application that uses the best of both worlds. If you’re just now joining us, you should check out this repository which contains relevant code for these articles.

在上一篇文章中,我开始探索Drupal 7和Elasticsearch引擎之间的集成。 目的是看我们如何结合这些开放源代码技术,以实现兼顾两者优势的高性能应用程序。 如果您现在才加入我们,则应该查看此存储库 ,其中包含这些文章的相关代码。

We’ll now create a small Silex application that reads data straight from Elasticsearch and returns it to the user.

现在,我们将创建一个小的Silex应用程序,该应用程序直接从Elasticsearch读取数据并将其返回给用户。

Silex应用 (Silex app)

Silex is a great PHP micro framework developed by the same people that are behind the Symfony project. It is in fact using mainly Symfony components but at a more simplified level. Let’s see how we can get started really quickly with a Silex app.

Silex是一个伟大PHP微框架,由Symfony项目背后的同一人开发。 实际上,它主要使用Symfony组件,但级别更简化。 让我们看看如何使用Silex应用程序真正快速地入门。

There is more than one way. You can add it as a dependency to an existent composer based project:

有不止一种方法。 您可以将其作为依赖项添加到现有的基于作曲家的项目中:

"silex/silex": "~1.2",

Or you can even create a new project using a nice little skeleton provided by the creator:

或者,您甚至可以使用创建者提供的漂亮的小骨架来创建新项目:

composer.phar create-project fabpot/silex-skeleton

Regardless of how your project is set up, in order to access Elasticsearch we’ll need to use its PHP SDK. That needs to be added to Composer:

无论您的项目如何设置,要访问Elasticsearch,我们都需要使用其PHP SDK 。 这需要添加到Composer中:

"elasticsearch/elasticsearch": "~1.0",

And if we want to use Twig to output data, we’ll need this as well (if not already there of course):

如果我们想使用Twig来输出数据,我们也将需要它(如果还没有的话):

"symfony/twig-bridge": "~2.3"

In order to use the SDK, we can expose it as a service to Pimple, the tiny Silex dependency injection container (much easier than it sounds). Depending on how our project is set up, we can do this in a number of places (see the repository for an example). But basically, after we instantiate the new Silex application, we can add the following:

为了使用SDK,我们可以将其作为服务提供给Pimple ,这是一个很小的Silex依赖项注入容器(比听起来容易得多)。 根据项目的设置方式,我们可以在很多地方进行此操作(请参见存储库中的示例)。 但是基本上,在实例化新的Silex应用程序之后,我们可以添加以下内容:

$app['elasticsearch'] = function() { return new Client(array()); };

This creates a new service called elasticsearch on our app that instantiates an object of the Elasticsearch Client class. And don’t forget we need to use that class at the top:

这将创建一个名为新服务elasticsearch我们的应用程序,实例化Elasticsearch的目标Client类。 并且不要忘记我们需要在顶部使用该类:

use Elasticsearch\Client;

Now, wherever we want, we can get the Elasticsearch client by simply referring to that property in the $app object:

现在,无论我们在哪里,我们都可以通过简单地在$app对象中引用该属性来获取Elasticsearch客户端:

$client = $app['elasticsearch'];

连接到Elasticsearch (Connecting to Elasticsearch)

In the previous article we’ve managed to get our node data into the node index with each node type giving the name of an Elasticsearch document type. So for instance, this will return all the article node types:

在上一篇文章中,我们设法将节点数据放入node索引中,每种节点类型都给出了Elasticsearch文档类型的名称。 因此,例如,这将返回所有article节点类型:

http://localhost:9200/node/article/_search

We’ve also seen how to instantiate a client for our Elasticsearch SDK. Now it’s time to use it somehow. One way is to create a controller:

我们还看到了如何为我们的Elasticsearch SDK实例化客户端。 现在是时候以某种方式使用它了。 一种方法是创建一个控制器:

<?php namespace Controller; use Silex\Application; use Symfony\Component\HttpFoundation\Response; class NodeController { /** * Shows a listing of nodes. * * @return \Symfony\Component\HttpFoundation\Response */ public function index() { return new Response('Here there should be a listing of nodes...'); } /** * Shows one node * * @param $nid * @param \Silex\Application $app * @return mixed */ public function show($nid, Application $app) { $client = $app['elasticsearch']; $params = array( 'index' => 'node', 'body' => array( 'query' => array( 'match' => array( 'nid' => $nid, ), ), ) ); $result = $client->search($params); if ($result && $result['hits']['total'] === 0) { $app->abort(404, sprintf('Node %s does not exist.', $nid)); } if ($result['hits']['total'] === 1) { $node = $result['hits']['hits']; return $app['twig']->render('node.html.twig', array('node' => reset($node))); } } }

Depending on how you organise your Silex application, there are a number of places this controller class can go. In my case it resides inside the src/Controller folder and it’s autoloaded by Composer.

根据组织Silex应用程序的方式,此控制器类可以在很多地方使用。 就我而言,它位于src/Controller文件夹中,由Composer自动加载。

We also need to create a route that maps to this Controller though. Again, there are a couple of different ways to handle this but in my example I have a routes.php file located inside the src/ folder and required inside index.php:

我们还需要创建一条映射到该Controller的路由。 同样,有两种不同的方法可以解决此问题,但在我的示例中,我有一个位于src/文件夹内的routes.php文件,并且在index.php内需要该文件:

<?php use Symfony\Component\HttpFoundation\Response; /** * Error handler */ $app->error(function (\Exception $e, $code) { switch ($code) { case 404: $message = $e->getMessage(); break; default: $message = 'We are sorry, but something went terribly wrong. ' . $e->getMessage(); } return new Response($message); }); /** * Route for /node */ $app->get("/node", "Controller\\NodeController::index"); /** * Route /node/{nid} where {nid} is a node id */ $app->get("/node/{nid}", "Controller\\NodeController::show");

So what happens in my example above? First, I defined an error handler for the application, just so I can see the exceptions being caught and print them on the screen. Not a big deal. Next, I defined two routes that map to my two controller methods defined before. But for the sake of brevity, I only exemplified what the prospective show() method might do:

那么在我上面的示例中会发生什么? 首先,我为应用程序定义了一个错误处理程序,以使我可以看到捕获到的异常并将其打印在屏幕上。 没什么大不了的。 接下来,我定义了两个路由,它们映射到之前定义的两个控制器方法。 但是为了简洁起见,我仅举例说明预期的show()方法可能会执行的操作:

Get the Elasticsearch client

获取Elasticsearch客户端 Build the Elasticsearch query parameters (similar to what we did in the Drupal environment)

构建Elasticsearch查询参数(类似于我们在Drupal环境中所做的工作) Perform the query

执行查询 Check for the results and if a node was found, render it with a Twig template and pass the node data to it.

检查结果,如果找到了节点,则使用Twig模板对其进行渲染,然后将节点数据传递给它。 If no results are found, abort the process with a 404 that calls our error handler for this HTTP code declared above.

如果未找到结果,请使用404中止该过程,该404会针对上述HTTP代码调用我们的错误处理程序。

If you want to follow this example, keep in mind that to use Twig you’ll need to register it with your application. It’s not so difficult if you have it already in your vendor folder through composer.

如果要遵循此示例,请记住,要使用Twig,您需要在应用程序中注册它。 如果您已经通过composer将其保存在供应商文件夹中,则并不难。

After you instantiate the Silex app, you can register the provider:

实例化Silex应用程序后,可以注册提供程序:

$app->register(new TwigServiceProvider());

Make sure you use the class at the top:

确保使用顶部的类:

use Silex\Provider\TwigServiceProvider;

And add it as a service with some basic configuration:

并通过一些基本配置将其添加为服务:

$app['twig'] = $app->share($app->extend('twig', function ($twig, $app) { return $twig; })); $app['twig.path'] = array(__DIR__.'/../templates');

Now you can create template files inside the templates/ folder of your application. For learning more about setting up a Silex application, I do encourage you to read this introduction to the framework.

现在,您可以在应用程序的templates/文件夹中创建模板文件。 要了解有关设置Silex应用程序的更多信息,建议您阅读此框架简介 。

To continue with our controller example though, here we have a couple of template files that output the node data.

不过,继续我们的控制器示例,这里我们有几个模板文件,它们输出节点数据。

Inside a page.html.twig file:

在page.html.twig文件中:

<!DOCTYPE html> <html> <head> {% block head %} <title>{% block title %}{% endblock %} - My Elasticsearch Site</title> {% endblock %} </head> <body> <div id="content">{% block content %}{% endblock %}</div> </body> </html>

And inside the node.html.twig file we used in the controller for rendering:

在控制器中用于渲染的node.html.twig文件中:

{% extends "page.html.twig" %} {% block title %}{{ node._source.title }}{% endblock %} {% block content %} <article> <h1>{{ node._source.title }}</h1> <div id="content"> {% if node._source.field_image %} <div class="field-image"> {% for image in node._source.field_image %} <img src="{{ image.url }}" alt="img.alt"/> {% endfor %} </div> {% endif %} {% if node._source.body %} <div class="field-body"> {% for body in node._source.body %} {{ body.value|striptags('<p><div><br><img><a>')|raw }} {% endfor %} </div> {% endif %} </div> </article> {% endblock %}

This is just some basic templating for getting our node data printed in the browser (not so fun otherwise). We have a base file and one that extends it and outputs the node title, images and body text to the screen.

这只是在浏览器中打印节点数据的一些基本模板(否则就不那么有趣了)。 我们有一个基础文件和一个扩展它的文件,并将节点标题,图像和正文文本输出到屏幕。

Alternatively, you can also return a JSON response from your controller with the help of the JsonResponse class:

另外,您还可以借助JsonResponse类从控制器返回JSON响应:

use Symfony\Component\HttpFoundation\JsonResponse;

And from your controller simply return a new instance with the values passed to it:

从您的控制器中简单地返回一个新实例,并将其值传递给它:

return new JsonResponse($node);

You can easily build an API like this. But for now, this should already work. By pointing your browser to http://localhost/node/5 you should see data from Drupal’s node 5 (if you have it). With one big difference: it is much much faster. There is no bootstrapping, theming layer, database query etc. On the other hand, you don’t have anything useful either out of the box except for what you build yourself using Silex/Symfony components. This can be a good thing or a bad thing depending on the type of project you are working on. But the point is you have the option of drawing some lines for this integration and decide its extent.

您可以轻松构建这样的API。 但是现在,这应该已经可以了。 通过将浏览器指向http://localhost/node/5您应该看到来自Drupal节点5的数据(如果有的话)。 有一个很大的不同:它快得多。 没有引导程序,主题层,数据库查询等。另一方面,除了使用Silex / Symfony组件构建的东西之外,您没有任何有用的东西。 根据您正在处理的项目类型,这可能是好事,也可能是坏事。 但是,关键是您可以为此集成绘制一些线并确定其范围。

One end of the spectrum could be building your entire front end with Twig or even Angular.js with Silex as the API backend. The other would be to use Silex/Elasticsearch for one Drupal page and use it only for better content search. Somewhere in the middle would probably be using such a solution for an entire section of a Drupal site that is dedicated to interacting with heavy data (like a video store or something). It’s up to you.

范围的一端可能是使用Twig甚至使用Silex作为API后端的Angular.js构建整个前端。 另一种方法是将Silex / Elasticsearch用于一个Drupal页面,并将其仅用于更好的内容搜索。 中间的某个地方可能会在Drupal网站的整个部分使用这种解决方案,该部分专门用于与大量数据(例如,视频存储等)进行交互。 由你决定。

结论 (Conclusion)

We’ve seen in this article how we can quickly set up a Silex app and use it to return some data from Elasticsearch. The goal was not so much to learn how any of these technologies work, but more of exploring the options for integrating them. The starting point was the Drupal website which can act as a perfect content management system that scales highly if built properly. Data managed there can be dumped into a high performance data store powered by Elasticsearch and retrieved again for the end users with the help of Silex, a lean and fast PHP framework.

我们已经在本文中看到了如何快速设置Silex应用程序并使用它从Elasticsearch返回一些数据。 目的不是要学习这些技术的工作原理,而是要探索整合这些技术的更多方法。 起点是Drupal网站,它可以充当完善的内容管理系统,如果构建正确,则可以高度扩展。 在那里管理的数据可以转储到由Elasticsearch支持的高性能数据存储中,并借助Silex(精益和快速PHP框架)再次为最终用户检索。

翻译自: https://www.sitepoint.com/integrate-elasticsearch-silex/

相关资源:jdk-8u281-windows-x64.exe
最新回复(0)