Modelagem de dados e design de esquema para o Atlas Search
Avalie esse Artigo
A modelagem de dados no MongoDB é a arte e a ciência de organizar dados dentro de um banco de dados para representar entidades, atributos e relacionamentos para lidar de forma ideal com os objetivos de negócios.
Existem três tipos de modelos de dados: conceituais, lógicos e físicos. Conceitualmente, para a busca, temos conteúdo e ele precisa ser rastreável e rastreável. Logicamente, o conteúdo geralmente é segregado por tipos de dados (por exemplo, livros e usuários de bibliotecas são tipos diferentes de entidades no sistema), cada tipo tendo seu próprio conjunto de atributos e relacionamentos.
O nível mais primitivo de modelagem de dados é onde o pedal encontra o metal, quase literalmente - no nível físico. O modelo físico consiste em um design de esquema, que define como os dados são estruturados em bancos de dados, coleções, fragmentos, campos, tipos de campo e índices.
A flexibilidade estrutural e de tipo do document model do MongoDB deixa o exercício do projeto de esquema para o desenvolvedor criar o melhor layout para as cargas de trabalho, dadas as restrições físicas, de hardware e de software. Os padrões de design emergiram da destilação e abstração de técnicas bem-sucedidas para lidar com várias necessidades comuns. E, como acontece com qualquer software, há restrições do sistema dentro das quais a pesquisa opera.
Este documento serve como um modelo para projetar esquemas para esses padrões de uso comuns que aproveitam o poder do sistema de pesquisa subjacente e funcionam dentro dos limites impostos pelos ambientes de hardware e software.
Ditado antigo da modelagem de dados: “The optimal grouping of objects into documents is determined by the workload. "
Nossa primeira parada no design de esquemas para pesquisa é entender as cargas de trabalho que nosso aplicativo exigirá do Atlas Search. Aqui estão os casos de uso comuns, considerando uma solicitação de pesquisa:
- Resultados da pesquisa paginados: retornam os principais documentos correspondentes (10 ou mais), em ordem de classificação ou de relevância, com ou sem facets
- Processar todos os Docs correspondentes: os Docs podem Go por estágios sucessivos de pipeline que precisam de todo o conjunto de resultados para continuar, como
$group
e$sort
- Retornar apenas contagens de facets, sem documentos correspondentes reais
- Sugestões relevantes conforme você digita
- Substitua $match por $search para indexar e consultar muitos mais campos do que os que podem ser indexados com índices b-tree do banco de dados.
- “Find anything anywhere " - práticas recomendadas; em comparação com $match e $elemMatch
Mestre de modelagem Wise: “We model to face and answer to constraints. "
A arquitetura do Atlas Search enquadra o que é possível. Dada a forma como o Atlas Search é criado, aqui está uma lista dos principais parâmetros físicos que são considerados nas decisões de projeto de esquema:
- O estágio
$search
consulta um único índice do Atlas Search. - Um índice do Atlas Search está vinculado a uma única coleção do Atlas.
- Um mapeamento define quais campos devem ser indexados de que maneira, mapeados por nome de campo e tipo de dados.
- Os critérios de pesquisa são usados para pontuar e retornar documentos de coleção correspondentes.
É importante destacar que essas decisões arquitetônicas específicas estão sujeitas a alterações à medida que o Atlas Search progride. Já existem vários trabalhos em andamento nos bastidores do produto que alteram e relaxam algumas dessas decisões arquitetônicas, abrindo a porta para algumas maneiras interessantes de fazer as coisas que não são possíveis atualmente. Esses padrões mudarão à medida que as capacidades físicas do sistema melhorarem. Como se costuma dizer, estamos trabalhando nisso... sempre!
A lista anterior de parâmetros operacionais físicos controlados pela arquitetura se encaixa na estrutura do pipeline de agregação como um estágio
$search
, que faz chamadas para um serviço de pesquisa criado sobre o poderoso mecanismo de pesquisaLucene. Vejamos ambas as extremidades da arquitetura, levando em consideração as cargas de trabalho típicas exigidas de $search e as restrições dentro das quais ela trabalha. Primeiro, vejamos como $search se encaixa no pipeline de agregação. Em seguida, vamos ver como a estrutura do índice subjacente opera no nível mais baixo do Atlas Search.O estágio
$search
deve ser, devido a escolhas práticas feitas durante a implementação, o primeiro estágio no aggregation pipeline (ou um estágio $unionWith). Não há nenhum conjunto de documentos de entrada para este estágio. O resultado desse estágio consiste em uma lista ordenada de documentos e alguns metadados de pesquisa adicionais. A saída do estágio$search
pode ser agregada ainda mais usando qualquer um dos estágios disponíveis que aceitam uma lista de documentos como entrada, como $limit
, $skip
, $project
, $addField
, $facet
, $match
, $group
, $lookupe outros, embora os estágios de agregação pós-pesquisa possam ter um efeito drástico no desempenho, conforme explicado aqui mais tarde.E $searchMeta? Esse estágio realiza uma pesquisa, mas em vez de retornar os documentos correspondentes, ele retorna metadados do resultado da pesquisa, como a contagem total de documentos e facets correspondentes, se tiverem sido solicitados. Esse estágio é útil se tudo o que você precisa são esses metadados, enquanto $search retorna todos esses mesmos metadados (como $$SEARCH_META) juntamente com os documentos correspondentes. Para usar $search ou $searchMeta: Se você quiser documentos correspondentes com ou sem facetas, use $search. Se você precisar apenas da contagem total e/ou das facetas, use $searchMeta.
Quando
$search
é executado a partir do mongod
(mongo "database ") nó que executa os estágios do pipeline de agregação, ele faz uma chamada remota para um processomongot
(mongo "text " baseado em Java). O processomongot
interface com as APIs do Lucene para indexação, pesquisa, classificação, realce e facet.Aspectos importantes a serem observados no que se refere ao design do esquema: São retornados documentos de coleções correspondentes, em ordem de classificação de relevância. Embora uma pesquisa possa resultar na correspondência de milhares, milhões ou até bilhões de documentos, o mecanismo de pesquisa subjacente foi projetado para corresponder, classificar e retornar os documentos rapidamente, fornecendo primeiro as melhores correspondências. O serviço
mongot
fornece resultados em lotes para o pipeline de agregação de chamada e será invocado até que o pipeline de chamada tenha esgotado o cursor e processado todas as correspondências ou entrado em curto-circuito em um estágio como$limit
.Aviso: a execução de pipelines de agregação na interface do usuário do Atlas ou do Compass aplicará um
$limit
implícito para mostrar somente os primeiros documentos resultantes. As pesquisas são rápidas. O mesmo pipeline de agregação, se executado ingenuamente em um ambiente de código que usa driver, pode puxar todos os cursores de documentos para uma estrutura de dados de array. A recuperação de todos os resultados da pesquisa em uma array pode consumir muito tempo e memória. Geralmente, é o padrão desejado $limit
resultados de pesquisa e paginar por meio deles conforme necessário. Se tudo correr bem, os melhores estarão no topo, então os usuários não precisarão ver muitos. :)Essas condições de trabalho do
$search
estágio informam algumas decisões de design: que ele deve ser o primeiro estágio no pipeline, que retorna documentos em ordem de relevância, que cruza os limites do processo retornando lotes de correspondências e, a menos que seja especificamente limitado, todas as correspondências os resultados da pesquisa serão, eventualmente, retornados. Este último ponto é importante — o número de resultados alimentadas pelo pipeline após $search tem um impacto direto e cada vez mais dramático no desempenho. Para obter o melhor resultado, crie um design para resultados limitados, apoiando-se no ajuste de relevância para obter o melhor primeiro. A paginação através dos resultados da pesquisa é eficiente erápida ao usar o mecanismo de token searchAfter .A escalabilidade do processo de pesquisa pode ser controlada adicionando e aumentando o uso de nós de pesquisa. Você pode definir nós específicos em seu cluster para executar somente o processo de
mongot
do Atlas Search . Quando o processo demongot
de Atlas Search é executado separadamente, a disponibilidade melhora e as cargas de trabalho são balanceadas. Para saber mais, consulte a documentação da Arquitetura de Nós de Pesquisa.No centro do Atlas Search reside o Lucene, uma biblioteca de mecanismos de pesquisa desenvolvida, poderosa e de código aberto. As abstrações sólidas do Lucene brilham através das camadas de chamada, bem como suas limitações.
"Index objects " são as unidades individuais de dados (a Lucene também as chama de "documents ", embora sejam chamadas de "index objects " para evitar mais confusão de terminologia, pois não são necessariamente um-para-um) adicionado ao índice Lucene, que consiste em um objeto de índice por documento de collection de banco de dados, mais um para cada documento incorporado mapeado. Os documentos incorporados são abordados em detalhes abaixo. A forma como os subdocumentos aninhados nos documentos principais da collection são tratados, dependendo da escala, pode afetar o design de fragmentação do modelo físico. Isso significa que o uso de documentos incorporados resultará em um número maior de objetos Lucene indexados e precisa ser considerado para o dimensionamento. O Lucene tem um limite de dois bilhões em objetos de índice. Ir além dos Docs 2B requer fragmentação.
Depois que uma configuração de índice é criada/atualizada, todos os documentos na collection são (re)indexados. Todos os campos de cada documento estão disponíveis para indexação, dadas as regras de mapeamento de configuração de índice. O espaço de armazenamento físico ocupado pela estrutura do índice depende inteiramente da configuração do índice.
O processo
mongot
alimenta o estágio$search
, lidando com solicitações sucessivas para extrair resultados de pesquisa em lotes. Essas chamadas remotas para lotes de resultados moldam o que é possível executar. O Lucene é otimizado para atender e paginar os documentos mais relevantes ou classificados rapidamente, satisfazendo o caso de uso de pesquisa mais comum de onde se espera que os usuários encontrem o que procuram nesses principais resultados. As queries geralmente correspondem a muito mais documentos do que seriam apresentados a um usuário de uma só vez, e somente os principais podem ser de interesse.Os lotes sucessivos de resultados solicitados pelo estágio
$search
permitem que os documentos reais retornados sejam cortados em um limite desejado. Independentemente de quantos resultados correspondentes são realmente devolvidos ao aggregation pipeline, a contagem exata de documentos correspondentes pode ser fornecida ou uma estimativa de limite inferior para melhor desempenho, para que o usuário possa ver a magnitude dos resultados disponíveis.As principais dicas de desempenho e limitações do sistema estão detalhadas na páginaAtlas Search Index Performance. Veja a seguir os principais destaques das restrições físicas relacionadas ao projeto de um esquema para casos de uso de pesquisa:
- Banco de dados e servidor de pesquisa são processos separados, potencialmente em nós separados para maior escalabilidade.
- Reunir em lote um grande conjunto de resultados de pesquisa entre os processos e a rede pode ser um grande gargalo.
- 2Objetos de índice B por índice do Atlas Search; os objetos de índice consistem em um para cada documento e um para cada documento incorporado explicitamente mapeado.
Atlas Search mapeia campos de documentos para índices em objetos de índice do Lucene por nome de campo e tipo de dados. Essa conexão direta com o nome e o tipo do campo determina o que é pesquisável e de que forma, e é uma consideração crucial na criação de um esquema para uma carga de trabalho de pesquisa.
A consistência na estrutura do documento é importante. O Lucene indexa campos com base nos nomes de campo, tipos e estrutura de cada documento de collection. É importante padronizar a estrutura do documento na collection apoiada pelo Atlas Search:
_id
: Se a coleção for mesclada/agregada especificamente para pesquisa a partir de dados estruturados de forma diferente em outras coleções, os identificadores estáveis serão importantes para as atualizações.- Não misture tipos de campo. Para um determinado nome de campo, seu tipo deve permanecer o mesmo em todos os documentos que tenham esse campo. Exemplo: Um campo
price
é um número de ponto flutuanteprice:37.99
em um documento. Ele não deve ser uma stringprice: "4.95"
em outro documento. - Se você planeja pesquisar ou facetar qualquer aspecto dos documentos aninhados, um layout consistente é crucial. Mapeamentos de índice são baseados no nome do campo e colocação estrutural.
- O nome do campo é a chave. A arquitetura do Atlas Search funciona melhor com uma estrutura
field_name
=value simples, pois a configuração do mapeamento do índice é primeiro orientada pelo nome de um campo, e as estruturas internas de dados do índice Lucene são baseadas nesse nome de campo.
Além disso, se os tipos de campo forem inconsistentes, cada um será indexado com base na configuração de mapeamento de campo para esse tipo específico. As consultas e o facetamento também são específicos do tipo. No exemplo
price
acima , uma consulta de intervalo numérico só seria capaz de corresponder ao valor numérico do preço, e a faceta de string só mostraria o valor do preço da string.Se e como um campo deve ser indexado ou não depende do mapeamento da configuração do índice.
A lógica de se um campo deve ser indexado segue este fluxo:
- Um mapeamento explícito de nome de campo tem precedência.
- Se o mapeamento dinâmico de campo estiver ativado e o campo não estiver explicitamente mapeado, ele será mapeado usando as regras padrão para o tipo de dados desse campo.
O mapeamento dinâmico de campos pode ser ativado no nível superior de um documento ou em qualquer subdocumento específico. Os atributos em documentos aninhados podem ser tratados com um mapeamento de nívelsub-
document
para encapsular uma seção ou todos os campos pesquisáveis do Atlas para um documento.Os detalhes do mapeamento de campos estão oficialmente documentados no documentoDefine Field Mappings (Definir mapeamentos de campos ).
Estes são os tipos de campo suportados pelo Atlas Search juntamente com os operadores de pesquisa disponíveis para estes tipos (* campos mapeados dinamicamente):
boolean
*: é igual a/emdate
*: igual a/em/perto/faixanumber
*: igual a/em/perto/faixaobjectId
*: é igual a/emstring
*: moreLikeThis/phrase/regex/text/wildcarddocument
*: mapeia campos aninhados para o documento principalembeddedDocument
: mapeia para separar o objeto de índice filhotoken
: igual/em/intervalogeo
: geoShape/geoWithin/nearautocomplete
- Facet:
stringFacet
,dateFacet
,numberFacet
O comportamento da indexação é configurável nas opções do tipo de dados dessa instância de campo específica. Os tipos de campos numéricos podem ser indexados para a capacidade de localizaçãonumérica
equals
, in
e range
e/ou faceta de intervalo (contagens por intervalo numérico em um conjunto de resultados) e, da mesma forma, para os tipos de campos de datas.Os valores booleanos são indexados para
equals
e in
de localizabilidade.Os campos de string são especiais, pois são analisados e divididos em termos indexados em uma estrutura de dados de índice invertida projetada para correspondência de nível de palavra/token. A capacidade de query com resultados rápidos e classificados por relevância em uma pilha de documentos de texto completo deriva da tokenização habilidosa e da análise e organização adicionais do texto da string em um índice invertido.
O tipo de dados dos valores dentro de uma matriz é usado para determinar como o campo é mapeado e indexado. As matrizes em si não são seu próprio tipo de campo. Por padrão, os documentos aninhados são mapeados como campos do tipo
document
, e todos os campos dentro dele são nivelados e indexados como se fossem campos no documento principal com sintaxe de nome pontilhado, trazendo todos os valores de campos no mesmo caminho relativo para uma matriz de valores nivelados. Há bons exemplos na documentaçãoComo indexar os elementos de uma matriz. Atualmente, não há suporte para facetas em matrizes de números e datas, mas todos os operadores de pesquisa para esses tipos são.O mantra do MongoDB "data that is accessed together is stored together " se baseia nos pontos fortes do banco de dados de documentos, gerando projetos eficazes ao aninhar dados relacionados e comumente acessados em valores únicos ou arrays de atributos e subdocumentos. As melhores práticas do Atlas Search ajustam o mantra para "data that is searched together is indexed together. " Pela natureza de sua arquitetura, um índice do Atlas Search indexa todos os campos mapeados de um documento juntos em uma única estrutura para que qualquer número de campos indexados possa ser usado em um query única para correspondência e classificação. Há pelo menos um objeto de índice por documento de coleção. As estruturas de documentos aninhadas apresentam um desafio de pesquisa interessante — essas estruturas devem ser correspondíveis de forma complexa e independente, ou talvez sejam consideradas mais diretamente um conjunto plano de atributos usado para corresponder ao documento principal?
É importante lembrar que os resultados de um
$search
são documentos de nível superior, e não documentos individuais aninhados por si só. Os documentos de nível superior retornados incluem o documento completo, inclusive a estrutura aninhada; os documentos aninhados não são retornados de forma independente ou separada de seus pais de nível superior.Existem duas maneiras de lidar com a indexação e a pesquisa de conteúdo em documentos aninhados:
document
e embeddedDocuments
.- Tipoachatado/
document
: Esse é o padrão com mapeamento dinâmico. Ele achata as estruturas de subdocumentos em valores no documento raiz. As consultas correspondem a essas matrizes achatadas e perdem a nuance da correspondência intra-embeddedDocument. embeddedDocuments
: você deve configurar isso — ele não vem por padrão. Ele indexa cada embeddedDocument especificado como um Lucene "index objects "separado vinculado ao objeto de índice pai. Ele permite queries específicas do embeddedDocument, semelhantes ao estágio$elemMatchdo banco de dados.
As estruturas de documentos aninhados podem ter várias camadas de profundidade e cada nível pode ser mapeado no Atlas Search como
document
ou embeddedDocuments
, possibilitando a indexação e a consulta complexa de vários níveis aninhados de profundidade. O fato de você poder mapear as coisas loucamente não significa que você deva fazê-lo. Em geral, é melhor ser mais simples e mais plano.Vamos ilustrar os prós e os contras das várias maneiras de indexar estruturas aninhadas com um exemplo de collection Parents com um único documento “Mom”, que tem dois filhos. A criança1 tem 5 anos de idade. A criança2 tem 11 anos de idade:
1 { 2 "name": "Mom", 3 "age": 37, 4 "children": [ 5 { 6 "name": "Kid1", 7 "age": 5 8 }, 9 { 10 "name": "Kid2", 11 "age": 11 12 } 13 ] 14 }
Use o mapeamento dinâmico ou um mapeamento explícito
document
para nivelar o documento de exemplo em um único objeto de índice no Lucene.Essa estrutura plana nos permite consultar os pais com um filho de 5 anos e também ter um filho chamado "Kid2 ", correspondente a este documento "Mom ". No entanto, não podemos consultar os pais que têm um filho de 5anos que também se chama "Kid2".
Este mesmo documento de exemplo, com
children
mapeado como um tipoembeddedDocuments
, cria três objetos de índice, um para cada documento incorporado mapeado e outro para o documento principal. Esta é a definição de mapeamento:1 { 2 "mappings": { 3 "dynamic": false, 4 "fields":{ 5 "children": [ 6 { 7 "type": "embeddedDocuments", 8 "dynamic": true 9 } 10 ] 11 } 12 } 13 }
Na estrutura do índice, esses documentos são colocalizados como um bloco físico contíguo. Qualquer atualização do documento, em qualquer parte de sua estrutura, reindexa esse documento, o que, por sua vez, reindexa todo o bloco de documentos incorporados mapeados.
Operacionalmente, uma atualização de um objeto de índice no Lucene é atomicamente uma exclusão e uma nova adição. A reindexação de um documento com documentos incorporados mapeados faz com que todo o bloco de objetos de índice seja excluído e adicionado novamente. A atualização constante de documentos com
embeddedDocuments
mapeados vasculha a estrutura de objetos indexados do Lucene; quanto mais documentos incorporados, mais difícil é adicionar, atualizar ou excluir um documento de collection.As pesquisas que consultam documentos incorporados são capazes de consultar cada documento "index object" incorporado independente separadamente e levar em consideração a pontuação associada na pontuação de classificação de relevância computada dos pais de nível superior.
Incorporar ou não? Depende. Os documentos incorporados mapeados têm um custo e só devem ser usados se a correspondência nuançada for necessária e a explosões no número de objetos de índice for gerenciável. E mesmo que esse tipo de correspondência seja necessário, outro fator decisivo é a escala — um único índice Lucene pode conter no máximo documentos 2B. Se você estiver aumentando essa escala, o sharding é a próxima etapa. Uma collection de 200documentos do banco de dados M cada um com 10 documentos incorporados explode em 2.2B () "index objects " ((10+1) x 200M), explodindo além do que pode ser possível ou acessível.
O caso de uso requer correspondência em toda a estrutura exata do subdocumento? Talvez esses subdocumentos mereçam ser documentos principais de primeira classe em uma coleção baseada em pesquisa, em vez de contorcer uma estrutura aninhada para obter algo que se encaixe melhor com uma estrutura mais plana e desenrolada. Ao considerar o mapeamento de documentos inseridos para casos de uso de pesquisa, considere também virar a estrutura do documento do avesso para que as entidades a serem retornadas de uma solicitação de pesquisa sejam documentos de primeira classe.
Os casos de uso de pesquisa que o Atlas Search deve apoiar precisam ser avaliados dentro das restrições físicas identificadas para produzir um design de esquema adequado. Atlas Search indexa o conteúdo com base diretamente no nome e tipo de dados de cada campo e retorna os principais documentos correspondentes das solicitações de pesquisa. Modelar documentos de acordo com as necessidades de casos de uso é simples; o que você indexa é o que você obtém: você indexa “movies” e $search retorna filmes, ou indexa produtos e $search retorna produtos. Os documentos na coleção são o que é retornado e, portanto, representam conceitualmente os tipos e a granularidade de “things” que o usuário está recebendo em resposta a uma consulta.
Vamos usar um exemplo de mecanismo de pesquisa de filmes: os filmes em si fazem sentido ser um item de resultado de pesquisa de primeira classe. E os membros do elenco? São simplesmente atributos e um meio de encontrar um filme? Ou são entidades de primeira classe que garantem ser um item independente nos resultados da pesquisa? Os itens de resultados de pesquisa de primeira classe devem ser modelados como documentos em uma coleção. Que tal
genre
? Os usuários de um sistema de pesquisa de filmes gostariam de acessar Documentários como uma entidade em si, digitando apenas "doc " e sendo a primeira sugestão?A experiência de pesquisa oferecida pelo seu aplicativo é uma parte crucial da utilidade e satisfação oferecidas aos usuários; a falta de um recurso de pesquisa de qualidade dissuadirá os usuários. Experiências de pesquisa agradáveis fornecem recursos como sugestões à medida que você digita, navegação facetada e realce de palavras-chave, ao mesmo tempo em que levam em consideração nossas preferências explícitas e implícitas, filtrando ou impulsionando itens. A qualidade da experiência de pesquisa de seus aplicativos consiste em muito mais do que apenas uma lista de documentos para uma consulta de pesquisa. Pode estar incorporando a pesquisa em áreas sutis, como seções "more like this" de páginas existentes, fornecendo filtragem sensível ao contexto e navegação de conteúdo organizado e outros aprimoramentos de UX. A conclusão é a seguinte: modele e construa para esta experiência.
Algumas perguntas que você deve se fazer ao iniciar o processo de modelagem:
- Que tipos de queries você espera?
- Como seu conteúdo é melhor organizado para navegação e capacidade de pesquisa?
- Quando os resultados da pesquisa são apresentados, qual a melhor forma de o aplicativo ajudar os usuários a restringir ou expandir sua pesquisa?
Não olhe para os padrões para encontrar um problema a ser resolvido, mas sim para encontrar os padrões que melhor se adaptam aos desafios que você está enfrentando. Vários dos padrões de design testados e verdadeiros do MongoDB funcionam bem para casos de uso de pesquisa.
Nome do padrão | Casos de uso de pesquisa |
---|---|
Calculado | O Padrão Computado se ajusta quando os dados enriquecidos podem ser calculados com antecedência e aproveitados para correspondência direta ou ponderação de relevância. |
Padrão de Entidade | O domínio Entity Pattern para pesquisa se ajusta à collection cruzada ou à pesquisa de entidades aninhadas. Encontrabilidade é fundamental. Essa collection especializada e a estrutura de índice do Atlas Search abordam os casos de uso "find anything anywhere " e "relevant as you type suggest ". Este padrão específico de pesquisa é discutido com mais detalhes em uma seção posterior. |
Referência estendida | O Padrão de Referência Estendido se encaixa quando os dados precisam ser reunidos para poderem ser pesquisados juntos, ao mesmo tempo em que vivem confortavelmente em outras coleções e estruturas para outras cargas de trabalho importantes. |
Polimórfico | No Padrão Polimórfico, os documentos poderiam representar entidades digitadas, onde os tipos representam uma hierarquia de modelo de objeto. Subdocumentos polimórficos podem ter facilmente configurações de mapeamento independentes. |
Coleção única | Se você está aproveitando o Single-Collection Pattern, está com sorte, pois esse padrão se encaixa mais diretamente no Atlas Search - um lugar para armazenar e encontrar tudo. Veja também: o padrão de entidade de domínio para pesquisa. |
Árvore | Quando você tem dados hierárquicos em casos de uso de pesquisa, o Padrão de Árvore fornece algumas ideias. As coleções de documentos são planas. Um conjunto simples de documentos é retornado de $search. Um campo que representa uma hierarquia como um simples "/path/string" pode trazer profundidade a um sistema plano. Um "/path/string" pode ser pesquisado por prefixo (por exemplo, wildcard em "/path" para obter documentos de lá e abaixo). |
O Padrão de Atributo representa pares de chave/valor em uma estrutura que não introduz um número potencialmente ilimitado de nomes de campo representando um par de chave/valor como uma estrutura de
{ k: "key", v: "value"}
JSON . Chaves são valores para um campok
; chaves são nomes de campo. O Atlas Search usa nomes de campo para mapeamento e, portanto, uma chave de atributo específica não pode ser mapeada e, ainda mais insidioso, é que v
valores podem ser de diferentes tipos de dados, mesmo que todos os valores de uma chave específica sejam do mesmo tipo devido à combinação de todos os valores em um único índice. O tipo de campoembeddedDocuments
pode ajudar no uso conservador do Padrão de Atributo para alguns recursos, mas isso vem com outras considerações (consulte a seção de documentos aninhados acima). O melhor curso de ação com atributos que precisam ser pesquisados? Modele-os como camposfield_name: value
simples nos documentos onde eles podem ser manipulados de maneira sensível ao tipo.Todos os valores de um determinado campo são indexados juntos e separados de outros campos.O Padrão de Entidade modela todas as principais entidades de domínio de uma forma que suporta os casos de uso "find anything anywhere" e "relevant as you type suggestions". As entidades são representadas como documentos de primeira classe em uma collection especializada e configuração de índice do Atlas Search ajustada para corresponder às entidades do domínio de várias maneiras e permitir fatores de classificação personalizados. Todas as suas entidades de domínio podem ser indexadas e localizáveis de várias maneiras usando esse padrão. Claro, a escala é importante, então esse não é um padrão prático para bilhões de coisas, embora muitas centenas de milhões sejam geralmente uma escala bastante tratável. Quantas entidades exclusivas você tem em seu sistema? Uma estimativa rápida para um sistema de catálogo de produtos realista, representando produtos, clientes e pedidos, poderia ter, digamos, 10mil produtos em 10 categorias, atendendo cerca de 1milhões de clientes, cada um com um endereço de cobrança e entrega dentro de qualquer um dos 50 Estados Unidos. Em cerca 200k cidades, isso seria 10k produtos + 1M de clientes + 2M de endereços + 50 estados + 200k cidades = ~3.2M entidades, o que não é grande coisa em termos de escala.
Se sua situação consiste em apenas uma única collection, com apenas um ou talvez mais tipos de entidades, e eles já estão modelados como documentos de primeira classe, esse padrão é efetivamente o que você já tem — todas as entidades de domínio representadas como documentos de primeira classe em uma única collection. Uma collection de todas as entidades de domínio combinadas e digitadas demonstra o Padrão de Collection Única.
É comum que sua collection principal represente um tipo de entidade como documentos e outras entidades de domínio como campos de metadados ou documentos aninhados. Por exemplo, vejamos os dados de filmes de amostra disponíveis no Atlas: Conforme o usuário digita, títulos de filmes seguramente devem ser sugeridos. Mas e os nomes dos membros do elenco? Posso encontrar filmes estrelados por Kaanu Reevers digitando apenas "kea"? E os documentários digitando apenas "doc"? Os campos
cast
(nome do ator) e genre
(campos, não documentos) são, para um aplicativo de pesquisa de filmes, objetos de entidade de domínio autenticamente de primeira classe e, em um sentido de encontrabilidade, devem ser documentos de primeira classe em uma coleção baseada pela Atlas Search.É um modelo simples com o seguinte esquema básico:
Campo | Descrição |
---|---|
_id | ID exclusivo para esta entidade, recomendado no formato
|
type | tipo de entidade/objeto, por exemplo, filme, marca, produto pessoal, categoria, save_search |
Nome | o nome ou título da entidade, que geralmente seria exclusivo por tipo |
É importante que os documentos da entidade tenham identificadores estáveis e exclusivos, pois as entidades serão atualizadas regularmente de sua fonte de coleta de verdade. A atribuição de um tipo a cada entidade permite filtrar, agrupar, aumentar ou facetar por tipo.
Além disso, modelar entidades diretamente como documentos individuais permite que cada uma carregue campos de metadados opcionais para ajudar a classificá-las, exibi-las, filtrá-las ou agrupá-las. No exemplo dos filmes, os documentos da entidade membro do elenco podem conter um número computado de filmes em que o ator participou e a classificação média de todos esses filmes. Esses tipos de valores calculados, agregados durante o processo de sincronização da coleção de entidades, exibem o Padrão Computado.
No centro dessa solução, o document model alimenta o campo
name
por meio de uma configuração de índice sofisticada, que o analisa de várias maneiras, permitindo um incrível poder de consulta e classificação.O padrão de entidade para pesquisa apresentado em Relevant As-You-Type Suggestions Search Solution (consulte a seção de abordagem de modelagem de dados) é especializado para o caso de uso as-you-type/autocomplete/typeahead.
- Como você sugere
- Pesquisas específicas do tipo (menu suspenso de categorias, estados, nomes)
- Índice geral de todas as (suas) coisas
Esta collection pode ser usada para iniciar pesquisas e limitar os resultados a apenas alguns (ou até mesmo apenas um) resultados, tornando a pesquisa de dados canônicos e mais detalhados simples e eficiente.
As operações básicas de pesquisa em uma collection de entidades tornam esses casos de uso diretos e de alto desempenho:
- Filtragem por tipo
- Entrada suspensa para cidades ("type" é igual a "city")
- Pesquisas salvas: registre o "saved searches " dos usuários como tipo de entidade "saved_search " com um campo "username " adicional em cada um desses tipos de documentos. À medida que o usuário digita, suas pesquisas salvas podem ser exibidas. Nenhuma collection adicional seria necessária — essa poderia ser a fonte da collection de informações verdadeiras para “saved searches.”. Para esse tipo de entidade, também seria sensato adicionar um carimbo de data/hora, para que elas pudessem ser classificadas por recente.
- Facetação por tipo
- À medida que um usuário digita, as entidades são retornadas e, além disso, os tipos de entidades encontradas e sua contagem no conjunto de resultados correspondentes podem ser retornados. Essas contagens são úteis para que os usuários vejam o contexto maior dos tipos de coisas que estão sendo correspondidas e a navegação filtrada por tipo a partir daí.
- Sem nenhum critério de filtro, uma faceta $seachMeta por
type
fornecerá rapidamente o conjunto completo de tipos de entidades disponíveis. Essas contagens globais podem ser úteis, novamente, para a navegação de seu "domain entity space" e também para fins de diagnóstico para garantir que o número de entidades de cada tipo corresponda às contagens da fonte de dados verdadeiros.
- Impulsionando por tipo
- Talvez faça sentido aumentar determinados tipos de entidades em relação a outros tipos de entidades nos resultados. À medida que um usuário digita uma pesquisa em um banco de dados de filmes, os tipos de entidade
genre
emovie
podem ser impulsionados em relação aos tipos de nome de membrocast
, de modo que as entidades mais comumente pesquisadas apareçam à frente em uma lista de sugestões. - Da mesma forma, as entidades de pesquisa salvas de um usuário podem ser priorizadas em relação aos tipos de entidades de produto ou categoria para aumentar o valor da experiência de seus clientes.
- Impulsionando por pesos de entidade
- Em uma pesquisa no banco de dados de filmes, aumente os membros do elenco por um fator relacionado às avaliações dos filmes em que participaram. A classificação média de todos os filmes de um ator não é o melhor peso a ser usado, pois prioriza um ator que só participou de um filme de alta audiência à frente de atores que já participaram de muitos filmes, a maioria dos quais teve uma boa classificação. Mas existem maneiras de impulsionar atores experientes usando a soma de todas as avaliações de seus filmes em vez de uma média. Quanto mais filmes bons eles assistirem, maior será o impulso. Os fatores de aumento baseados nos próprios dados da entidade fornecem uma maneira flexível de adicionar ponderações “smart” aos resultados com base nas metas de sua empresa.
Você já tem dados e eles são bem modelados para outros casos de uso aninhados em subestruturas de documentos relacionados. No entanto, a estrutura desses dados não se presta a ser localizável de primeira classe. Deixe os dados onde eles se encaixam melhor nos outros casos de uso, mantendo a fonte da verdade exatamente onde ela já está. As entidades exclusivas aninhadas em documentos de outras coleções geralmente podem ser extraídas e agrupadas de forma exclusiva, computando quaisquer valores úteis ao longo do caminho. A manutenção de uma sincronização de dados na coleção de entidades requer consideração e um processo de implementação.
Um ótimo exemplo de um processo de exportação/merge vem dos dados da collection de filmes, em que o gênero é um atributo de um filme, mas vale a pena ser uma entidade de domínio de primeira classe. Da collection de filmes, desenrolamos o campo gêneros de seu valor por filme aninhado e, em seguida, agrupamos os gêneros em valores únicos, contando o número de filmes para cada gênero ao longo do caminho. Em seguida, formatamos os gêneros únicos no esquema de collection de entidades (ID, tipo, nome etc.) em que ID é exclusivo por gênero e feito para caber exclusivamente no espaço ID de uma collection combinada de vários tipos de entidade. E, finalmente, esses documentos de entidades de gênero são mesclados na collection abrangente de entidades. O estágio $merge substituirá documentos com o mesmo ID, tornando importante identificar entidades de forma única e estável para que elas possam ser facilmente atualizadas.
1 movies.aggregate([ 2 { 3 $unwind: "$genres", 4 }, 5 { 6 $group: { 7 _id: "$genres", 8 num_movies: { $count: {} }, 9 }, 10 }, 11 { 12 $project: { 13 _id: {$concat: [ "genre", "-", "$_id" ]}, 14 type: "genre", 15 name: "$_id", 16 weight: "$num_movies" 17 } 18 }, 19 { $merge: { into: "entities" } } 20 ]);
Cada tipo de entidade pode ter seu próprio processo de sincronização e campos adicionais específicos do tipo.
A configuração do índice da coleção
entities
especifica os mapeamentos nos campostype
e name
, deixando-o mapeado dinamicamente para acomodar campos personalizados adicionais, conforme necessário.Vale a pena destacar algumas partes específicas dessa configuração. O campo
type
de entidades é indexado de duas maneiras diferentes: comotoken
para filtragem ou reforço por valor exato e stringFacet
para necessidades de facetamento por tipo.1 "type": [ 2 { 3 "type": "token" 4 }, 5 { 6 "type": "stringFacet" 7 } 8 ]
O cerne da encontrabilidade da entidade decorre das estratégias de indexação aplicadas ao campo
name
. O Atlas Search fornece uma poderosa técnica de indexação "multi" para campos de string, onde esse valor de string é indexado de várias maneiras para facilitar qualquer número de maneiras de combiná-lo. As strings são analisadas, um processo que cria uma série de unidades indexáveis chamadas termos. Os termos representam palavras, fragmentos de caracteres, fonética ou outros truques de extração lexical. Na configuração de exemplo mencionada acima, o campo de nome é indexado apenas com a borda esquerda ("starts with"), como texto em inglês ("search", "searches", "searching", "searched" todos indexados da mesma forma), minúsculas (correspondência sem distinção entre maiúsculas e minúsculas), fonética ("sounds like"), shingled (pares de palavras concatenadas e indexadas juntas, boas para aumentar a relevância de palavras comumente usadas juntas), e usando a análise de extração delimitada por quebra de palavras independente de idioma padrão.Essas várias formas de analisar o campo
name
fornecem aos operadorestext
e phrase
formas potentes de correspondência e classificação. Aqui está um exemplo de um cenário de consulta de sugestão do tipo "as-you-type", combinando livremente com muito pouco texto de consulta ("matr") e, ainda assim, impulsionando as melhores correspondências para o topo:A partir deste Atlas Search Playground, ponderamos cada variante analisada do campo
name
de forma diferente e, em seguida, multiplicamos o resultado por qualquer peso especificado na entidade correspondente.:1 [ 2 { 3 "$search": { 4 "compound": { 5 "should": [ 6 { 7 "text": { 8 "query": "matr", 9 "path": { 10 "value": "name", 11 "multi": "exact" 12 }, 13 "score": { 14 "boost": { 15 "value": 10 16 } 17 } 18 } 19 }, 20 { 21 "wildcard": { 22 "query": "matr*", 23 "path": { 24 "value": "name", 25 "multi": "lowercased" 26 }, 27 "allowAnalyzedField": true, 28 "score": { 29 "boost": { 30 "value": 5 31 } 32 } 33 } 34 }, 35 { 36 "text": { 37 "query": "matr", 38 "path": { 39 "value": "name", 40 "multi": "shingled" 41 }, 42 "score": { 43 "boost": { 44 "value": 7 45 } 46 } 47 } 48 }, 49 { 50 "phrase": { 51 "query": "matr", 52 "path": { 53 "value": "name", 54 "multi": "edge" 55 }, 56 "slop": 100 57 } 58 }, 59 { 60 "text": { 61 "query": "matr", 62 "path": { 63 "value": "name", 64 "multi": "english" 65 }, 66 "fuzzy": { 67 "prefixLength": 1, 68 "maxExpansions": 10 69 }, 70 "score": { 71 "boost": { 72 "value": 0.7 73 } 74 } 75 } 76 }, 77 { 78 "text": { 79 "query": "matr", 80 "path": { 81 "value": "name", 82 "multi": "phonetic" 83 }, 84 "score": { 85 "boost": { 86 "value": 0.5 87 } 88 } 89 } 90 } 91 ], 92 "score": { 93 "boost": { 94 "path": "weight", 95 "undefined": 1 96 } 97 } 98 }, 99 "scoreDetails": true, 100 "highlight": { 101 "path": [ 102 "name", 103 { 104 "value": "name", 105 "multi": "edge" 106 }, 107 { 108 "value": "name", 109 "multi": "lowercased" 110 }, 111 { 112 "value": "name", 113 "multi": "english" 114 }, 115 { 116 "value": "name", 117 "multi": "shingled" 118 } 119 ] 120 } 121 } 122 }, 123 { 124 "$limit": 10 125 }, 126 { 127 "$project": { 128 "name": 1, 129 "type": 1, 130 "score": { 131 "$meta": "searchScore" 132 } 133 } 134 } 135 ]
A pesquisa em vários campos indexados, de forma eficiente, em combinações entre si é uma superpotência do Atlas Search — e é a chave para uma relevância de resultados nuançada e controlável.
Para evitar colisões de nomes de campo em qualquer campo específico de tipo de entidade personalizada, os campos podem ser aninhados em subdocumentos específicos de tipo, como esta subestrutura
book
:1 { 2 _id: 1, 3 type: 'book', 4 name: 'Lucene in Action', 5 book: { 6 pages: 472, 7 .... 8 } 9 }
A configuração do índice do Atlas Search da coleção de entidades poderia então adicionar mapeamentosespecíficos do tipo
document
para substituir os mapeamentos dinâmicos padrão existentes, talvez tornando facetable o número de páginas das entidades de livros:1 'book': { 2 type: 'document', 3 fields: { 4 pages: { 5 type: numberFacet 6 } 7 } 8 }
- Comece com o resultado final em mente
- Qual é a UI/UX que está sendo alimentada pela pesquisa?
- Que tipos de objetos/entidades são retornados e exibidos?
- Itens de modelo a serem retornados de queries de pesquisa como documentos de primeira classe em sua própria collection.
- Os campos com o mesmo nome devem ter o mesmo tipo de dados em todos os documentos.
- “Data that is searched together, is indexed together.”
Junte-se a nós no fórum da comunidade Atlas Search para discutir melhor a modelagem de dados e o projeto de esquema para o Atlas Search.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.