{"id":410,"date":"2021-12-15T11:45:00","date_gmt":"2021-12-15T14:45:00","guid":{"rendered":"https:\/\/suspensao.blog.br\/descrenca\/?p=410"},"modified":"2021-12-22T14:43:28","modified_gmt":"2021-12-22T17:43:28","slug":"liferay-elasticsearch-2-arquitetura","status":"publish","type":"post","link":"https:\/\/suspensao.blog.br\/descrenca\/liferay-elasticsearch-2-arquitetura\/","title":{"rendered":"Busca textual no Liferay Portal com Elasticsearch &#8211; Parte 2: Arquitetura"},"content":{"rendered":"\n<p>Quando <a href=\"https:\/\/suspensao.blog.br\/descrenca\/liferay-elasticsearch-1-historia\/\">migramos de Lucene para Elasticsearch<\/a>, Liferay manteve o mesmo processo: ao salvar uma entidade, indexamos seus campos. S\u00f3 que, agora, no Elasticsearch.<\/p>\n\n\n\n<p>Contudo, Elasticsearch n\u00e3o \u00e9 uma biblioteca: \u00e9 um sistema servidor altamente distribu\u00eddo, rodando em <em>cluster<\/em>s. Isto nos for\u00e7ou a tomar novas decis\u00f5es, e nos presenteou com algumas li\u00e7\u00f5es valiosas. Para entend\u00ea-las, conv\u00e9m revisar como Elasticsearch pode ser usado.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">O modelo de programa\u00e7\u00e3o de Elasticsearch<\/h2>\n\n\n\n<p>No Elasticsearch, os dados s\u00e3o salvos como pares de chave-valor, agrupados em documentos.  Os documentos representam as inst\u00e2ncias das entidades.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"461\" data-permalink=\"https:\/\/suspensao.blog.br\/descrenca\/liferay-elasticsearch-2-arquitetura\/documents-indices\/\" data-orig-file=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?fit=2029%2C1912&amp;ssl=1\" data-orig-size=\"2029,1912\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"documents.indices\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?fit=300%2C283&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?fit=1024%2C965&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?resize=768%2C724&#038;ssl=1\" alt=\"\" class=\"wp-image-461\" width=\"768\" height=\"724\" srcset=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?resize=1024%2C965&amp;ssl=1 1024w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?resize=300%2C283&amp;ssl=1 300w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?resize=768%2C724&amp;ssl=1 768w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?resize=1536%2C1447&amp;ssl=1 1536w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/documents.indices.png?w=2029&amp;ssl=1 2029w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Um \u00edndice contem v\u00e1rios documentos. Para efeitos pr\u00e1ticos, todos os documentos de um \u00edndice s\u00e3o mesmo tipo (ao contr\u00e1rio de SGBDs, que aceitam v\u00e1rias tabelas em um banco de dados). O tipo define que campos s\u00e3o encontrados nos documentos e \u00e9 usualmente din\u00e2mico, permitindo que campos novos sejam adicionados por mera inser\u00e7\u00e3o.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">V\u00e1rios \u00edndices para v\u00e1rios portais<\/h2>\n\n\n\n<p>\u00c9 muito comum trabalhar, no Elasticsearch, com v\u00e1rios \u00edndices diferentes em um mesmo <em>cluster<\/em>, para o mesmo formato de dados. Como seriam os \u00edndices do Liferay. Para responder isso, \u00e9 necess\u00e1rio ter em mente que Liferay \u00e9 <em>multi-tenant<\/em>.<\/p>\n\n\n\n<p>Sabe quando voc\u00ea entra, digamos, em wordpress.com ou blogspot.com e cria um blog? Seu blog \u00e9 totalmente independente de qualquer outro no mesmo site. O mesmo se aplica ao Liferay Portal, que permite criar <em>inst\u00e2ncias<\/em> independentes em uma mesma instala\u00e7\u00e3o.<\/p>\n\n\n\n<p>Os engenheiros decidiram ent\u00e3o que cada inst\u00e2ncia teria seu pr\u00f3prio \u00edndice no Elasticsearch. Separar os dados desta maneira nos permitiu controlar melhor o acesso de uma inst\u00e2ncia, assim como nos deu flexibilidade para otimizar Elasticsearch.<\/p>\n\n\n\n<p>Por outro lado, embora houvesse v\u00e1rios \u00edndices, todos teriam o mesmo formato. Como seria esse formato?<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Tudo junto e misturado<\/h2>\n\n\n\n<p>Seguindo as recomenda\u00e7\u00f5es da Elastic, cada \u00edndice teria um s\u00f3 tipo. Neste tipo, indexamos as mais diversas entidades.<\/p>\n\n\n\n<p>Na hora em que uma entidade \u00e9 salva no banco de dados, os valores de suas colunas s\u00e3o indexados em um s\u00f3 tipo de documento. Assim, o post de blog, o artigo do CMS, o coment\u00e1rio no f\u00f3rum&#8230; todos ser\u00e3o representados pelo mesmo formato. O t\u00edtulo do blog, do evento, da wiki etc. se tornar\u00e3o o campo <kbd>title<\/kbd> de v\u00e1rios documentos. O mesmo se passa com campos como <kbd>content<\/kbd>, <kbd>summary<\/kbd>, <kbd>description<\/kbd>&#8230;<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?ssl=1\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" data-attachment-id=\"474\" data-permalink=\"https:\/\/suspensao.blog.br\/descrenca\/liferay-elasticsearch-2-arquitetura\/all-in-one-2\/\" data-orig-file=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?fit=1841%2C1265&amp;ssl=1\" data-orig-size=\"1841,1265\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"all-in-one\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?fit=300%2C206&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?fit=1024%2C704&amp;ssl=1\" src=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?resize=768%2C528&#038;ssl=1\" alt=\"\" class=\"wp-image-474\" width=\"768\" height=\"528\" srcset=\"https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?resize=1024%2C704&amp;ssl=1 1024w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?resize=300%2C206&amp;ssl=1 300w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?resize=768%2C528&amp;ssl=1 768w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?resize=1536%2C1055&amp;ssl=1 1536w, https:\/\/i0.wp.com\/suspensao.blog.br\/descrenca\/wp-content\/uploads\/2021\/12\/all-in-one.png?w=1841&amp;ssl=1 1841w\" sizes=\"auto, (max-width: 768px) 100vw, 768px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Estes campos representam caracter\u00edsticas comuns a v\u00e1rias entidades. Quando todas elas s\u00e3o indexadas em um s\u00f3 \u00edndice, com um <em>schema<\/em> uniforme, a busca se torna mais simples: basca procurar pela <em>string<\/em> nestes documentos.<\/p>\n\n\n\n<p>Os documentos Elasticsearch tamb\u00e9m cont\u00eam bastante metadados, sendo alguns dos mais importantes o campo <kbd>entryClassName<\/kbd> (o tipo da entidade que o documento representa, geralmente o nome de uma classe Java) e <kbd>entryClassPK<\/kbd> (identificador da entidade na tabela SQL). Desta forma, podemos encontrar o que o usu\u00e1rio procura e, a partir da\u00ed, recuperar a entidade correta do bando de dados.<\/p>\n\n\n\n<p>Esta arquitetura \u00e9 uma heran\u00e7a da busca com Lucene mas, nada surpreendentemente,  funcionou perfeitamente com Elasticsearch. Esta foi uma de nossas primeiras li\u00e7\u00f5es:<\/p>\n\n\n\n<figure class=\"wp-block-pullquote\"><blockquote><p>Para implementar busca texutal, junte v\u00e1rios tipos de unidade em um s\u00f3 tipo de documento.<\/p><\/blockquote><\/figure>\n\n\n\n<p>Decidida a arquitetura dos dados, a pr\u00f3xima quest\u00e3o a resolver era: como indexar e buscar as entidades no \u00edndice da inst\u00e2ncia. Este ser\u00e1 o tema da parte 3 desta s\u00e9rie.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Quando migramos de Lucene para Elasticsearch, Liferay manteve o mesmo processo: ao salvar uma entidade, indexamos seus campos. S\u00f3 que, agora, no Elasticsearch. Contudo, Elasticsearch n\u00e3o \u00e9 uma biblioteca: \u00e9 um sistema servidor altamente distribu\u00eddo, rodando em clusters. Isto nos for\u00e7ou a tomar novas decis\u00f5es, e nos presenteou com algumas li\u00e7\u00f5es valiosas. Para entend\u00ea-las, conv\u00e9m [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[127,126,125,1],"tags":[],"class_list":["post-410","post","type-post","status-publish","format-standard","hentry","category-busca-textual","category-elasticsearch","category-liferay","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p23QLV-6C","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/posts\/410","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/comments?post=410"}],"version-history":[{"count":8,"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/posts\/410\/revisions"}],"predecessor-version":[{"id":477,"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/posts\/410\/revisions\/477"}],"wp:attachment":[{"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/media?parent=410"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/categories?post=410"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/suspensao.blog.br\/descrenca\/wp-json\/wp\/v2\/tags?post=410"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}