├── .gitignore
├── README.md
├── docker-compose.yml
├── package.json
├── src
    ├── DBController.ts
    ├── PhotoController.ts
    ├── client
    │   └── elasticsearch.ts
    └── server.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /yarn.lock
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
🎉
 4 |    Sobre    |   
 5 |   Conceitos ensinados   |   
 6 |   Material de apoio   |   
 7 |     Como baixar
 8 | 
 9 | 
10 | # 🔖 Sobre
11 | 
12 | Esse projeto tem como objetivo ensinar um pouco sobre Elasticsearch e Kibana.  Clique aqui  para assistir o vídeo
13 | 
14 | ## ✍🏻 Conceitos ensinados
15 | 
16 | Durante o desenvolvimento, foi ensinado sobre `Elasticsearch`, que é um mecanismo de busca super rápido e `Kibana` que é um dashboard para acessar os dados do Elasticsearch.
17 | 
18 | ## 🗂 Material de apoio
19 | 
20 | - [Elasticsearch e Kibana](https://www.elastic.co/pt/elastic-stack)
21 | - [Elasticsearch para NodeJS](https://www.npmjs.com/package/elasticsearch)
22 | - [API do Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/16.x/api-reference.html)
23 | 
24 | ## 👍🏻 Como baixar
25 | 
26 | ```bash
27 | 
28 |     // Clonar repositório
29 |     $ git clone https://github.com/danileao/elasticsearch
30 | 
31 |     // Acessar diretório
32 |     $ cd elasticsearch
33 | 
34 |     // Instalar dependências
35 |     $ yarn
36 | 
37 |     // Iniciar projeto
38 |     $ yarn start
39 | ```
40 | 
41 | ---
42 | 
43 | Desenvolvido por  💜  Daniele Leão Evangelista 
44 | 
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
 1 | version: "3"
 2 | services:
 3 |   elasticsearch01:
 4 |     image: docker.elastic.co/elasticsearch/elasticsearch:7.9.2
 5 |     container_name: elasticsearch01
 6 |     ports: 
 7 |       - 9200:9200
 8 |       - 9300:9300
 9 |     environment:
10 |       discovery.type: single-node
11 |     networks:
12 |       - elastic
13 |   
14 |   kibana01:
15 |     image: docker.elastic.co/kibana/kibana:7.9.2
16 |     container_name: kibana01
17 |     ports:
18 |       - 5601:5601
19 |     environment:
20 |       ELASTICSEARCH_URL: http://elasticsearch01:9200
21 |       ELASTICSEARCH_HOSTS: http://elasticsearch01:9200
22 |     networks:
23 |       - elastic
24 | 
25 | networks:
26 |   elastic:
27 |     driver: bridge
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "elasticsearch",
 3 |   "version": "1.0.0",
 4 |   "main": "index.js",
 5 |   "license": "MIT",
 6 |   "scripts": {
 7 |     "dev": "ts-node-dev src/server.ts"
 8 |   },
 9 |   "devDependencies": {
10 |     "@types/elasticsearch": "^5.0.36",
11 |     "@types/express": "^4.17.8",
12 |     "@types/pg": "^7.14.5",
13 |     "ts-node-dev": "^1.0.0-pre.65",
14 |     "typescript": "^4.0.3"
15 |   },
16 |   "dependencies": {
17 |     "elasticsearch": "^16.7.1",
18 |     "express": "^4.17.1",
19 |     "pg": "^8.4.1"
20 |   }
21 | }
22 | 
--------------------------------------------------------------------------------
/src/DBController.ts:
--------------------------------------------------------------------------------
 1 | import { Request, Response } from 'express';
 2 | import { Client } from 'pg';
 3 | 
 4 | class DBController {
 5 | 
 6 | 
 7 |   async create(request: Request, response: Response) {
 8 |     const dataInicial = new Date().getTime();
 9 |     const client = new Client({
10 |       host:'IP.DO.BANCO',
11 |       port: 5432,
12 |       database: 'postgres',
13 |       password: 'SENHA',
14 |       user: 'postgres'
15 |     });
16 | 
17 |     await client.connect();
18 | 
19 |     const { rows } = await client.query('SELECT * FROM PHOTOS');
20 | 
21 |     const dataFinal = new Date().getTime();
22 | 
23 |     console.log('O resultado foi', (dataFinal - dataInicial))
24 | 
25 |     return response.json(rows);
26 |   }
27 | 
28 | }
29 | 
30 | export default new DBController;
--------------------------------------------------------------------------------
/src/PhotoController.ts:
--------------------------------------------------------------------------------
  1 | import { Request, Response } from "express";
  2 | import { Client } from "pg";
  3 | import getClient from "./client/elasticsearch";
  4 | 
  5 | 
  6 | class PhotoController {
  7 | 
  8 |   async create(request: Request, response: Response) {
  9 |     const client = new Client({
 10 |       host:'IP.DO.BANCO',
 11 |       port: 5432,
 12 |       database: 'postgres',
 13 |       password: 'SENHA',
 14 |       user: 'postgres'
 15 |     });
 16 | 
 17 |     await client.connect();
 18 | 
 19 |     const { rows } = await client.query('SELECT * FROM PHOTOS');
 20 | 
 21 |     for await(let row of rows) {
 22 |       await getClient().index({
 23 |         index: 'photos',
 24 |         type: 'type_photos',
 25 |         body: row
 26 |       }, (erro) => {
 27 |         if(erro) {
 28 |           return response.status(400).json({error: erro})
 29 |         }
 30 |       })
 31 |     }
 32 | 
 33 |     return response.json({ message: 'Index ok!'})
 34 |   }
 35 | 
 36 |   async findAll(request: Request, response: Response) {
 37 | 
 38 |     const dataInicial = new Date().getTime();
 39 | 
 40 |     const data = await getClient().search({
 41 |       index: 'photos',
 42 |       size: 6000
 43 |     });
 44 | 
 45 |     const dataFinal = new Date().getTime();
 46 | 
 47 |     console.log('O resultado do elasticsearch foi', (dataFinal - dataInicial));
 48 | 
 49 |     return response.json(data);
 50 |   }
 51 | 
 52 | 
 53 |   async findById(request: Request, response: Response) {
 54 | 
 55 |     const { id }  = request.params;
 56 |     
 57 |     const data = await getClient().search({
 58 |       index: 'photos',
 59 |       q: `id:${id}`
 60 |     });
 61 | 
 62 |     return response.json(data.hits.hits)
 63 |   }
 64 | 
 65 |   async createPhoto(request: Request, response: Response) {
 66 |     const photo = {
 67 |       "albumid": null,
 68 |       "id": 99999,
 69 |       "title": "Title De Teste",
 70 |       "url": "https://via.placeholder.com/600/bf37f1",
 71 |       "thumbnailurl": null
 72 |     }
 73 | 
 74 |     const data = await getClient().index({
 75 |       index: 'photos',
 76 |       type: 'type_photos',
 77 |       body: photo,
 78 |       
 79 |     });
 80 | 
 81 |     return response.json(data)
 82 |   }
 83 | 
 84 |   async findByQuery(request: Request, response: Response) {
 85 | 
 86 |     const data = await getClient().search({
 87 |       index: 'photos',
 88 |       body: {
 89 |         query: {
 90 |           term: {
 91 |             "title.keyword": 'Title De Teste'
 92 |           }
 93 |         }
 94 |       },
 95 |     })
 96 | 
 97 |     return response.json(data);
 98 |   }
 99 | 
100 | }
101 | 
102 | export default new PhotoController;
--------------------------------------------------------------------------------
/src/client/elasticsearch.ts:
--------------------------------------------------------------------------------
 1 | import elasticsearch from 'elasticsearch';
 2 | 
 3 | 
 4 | function getClient() {
 5 |   const client = new elasticsearch.Client({
 6 |     host: 'localhost:9200',
 7 |     // log: 'trace'
 8 |   });
 9 | 
10 |   return client;
11 | }
12 | 
13 | export default getClient;
--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------
 1 | import express, { Request, Response } from 'express';
 2 | import getClient from './client/elasticsearch';
 3 | import DBController from './DBController';
 4 | import PhotoController from './PhotoController';
 5 | 
 6 | 
 7 | const app = express();
 8 | 
 9 | 
10 | app.get('/', async (request: Request, response: Response) => {
11 | 
12 |   const client = getClient();
13 | 
14 |   // Criar um registro no elasticsearch
15 |   const result = await client.index({
16 |     index: 'elastic_teste',
17 |     type: 'type_elastic_teste',
18 |     body: {
19 |       user: 'Daniele',
20 |       password: 'sd8234udf',
21 |       email: 'dani.leao89@gmail.com'
22 |     }
23 |   });
24 | 
25 |   // Fazer uma busca
26 | 
27 |   return response.json(result);
28 | })
29 | 
30 | 
31 | app.get('/db/create', DBController.create);
32 | app.get('/photos/create', PhotoController.create);
33 | app.get('/photos/findAll', PhotoController.findAll);
34 | app.get('/photos/findById/:id', PhotoController.findById);
35 | app.get('/photos/createPhoto', PhotoController.createPhoto);
36 | 
37 | app.get('/photos/findByQuery', PhotoController.findByQuery);
38 | 
39 | 
40 | 
41 | 
42 | 
43 | app.listen(3333, () => console.log('Running'));
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "compilerOptions": {
 3 |     /* Visit https://aka.ms/tsconfig.json to read more about this file */
 4 | 
 5 |     /* Basic Options */
 6 |     // "incremental": true,                   /* Enable incremental compilation */
 7 |     "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
 8 |     "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
 9 |     // "lib": [],                             /* Specify library files to be included in the compilation. */
10 |     // "allowJs": true,                       /* Allow javascript files to be compiled. */
11 |     // "checkJs": true,                       /* Report errors in .js files. */
12 |     // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
13 |     // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
14 |     // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
15 |     // "sourceMap": true,                     /* Generates corresponding '.map' file. */
16 |     // "outFile": "./",                       /* Concatenate and emit output to single file. */
17 |     // "outDir": "./",                        /* Redirect output structure to the directory. */
18 |     // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
19 |     // "composite": true,                     /* Enable project compilation */
20 |     // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
21 |     // "removeComments": true,                /* Do not emit comments to output. */
22 |     // "noEmit": true,                        /* Do not emit outputs. */
23 |     // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
24 |     // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
25 |     // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
26 | 
27 |     /* Strict Type-Checking Options */
28 |     "strict": true,                           /* Enable all strict type-checking options. */
29 |     // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
30 |     // "strictNullChecks": true,              /* Enable strict null checks. */
31 |     // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
32 |     // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
33 |     // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
34 |     // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
35 |     // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
36 | 
37 |     /* Additional Checks */
38 |     // "noUnusedLocals": true,                /* Report errors on unused locals. */
39 |     // "noUnusedParameters": true,            /* Report errors on unused parameters. */
40 |     // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
41 |     // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
42 | 
43 |     /* Module Resolution Options */
44 |     // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
45 |     // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
46 |     // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
47 |     // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
48 |     // "typeRoots": [],                       /* List of folders to include type definitions from. */
49 |     // "types": [],                           /* Type declaration files to be included in compilation. */
50 |     // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
51 |     "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
52 |     // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
53 |     // "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */
54 | 
55 |     /* Source Map Options */
56 |     // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
57 |     // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
58 |     // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
59 |     // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
60 | 
61 |     /* Experimental Options */
62 |     // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
63 |     // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
64 | 
65 |     /* Advanced Options */
66 |     "skipLibCheck": true,                     /* Skip type checking of declaration files. */
67 |     "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
68 |   }
69 | }
70 | 
--------------------------------------------------------------------------------