Representar los diferentes tipos dentro de un índice, como un usuario, un producto, etc.
Representa tallos de palabras, exclusivos de todo el índice. (Por ejemplo, la ejecución es un tallo de las palabras corriendo, corredor, ejecución, etc.). Se calcula y almacena una frecuencia de documento inversa contra la palabra para proporcionar una IDF de todo el índice que puede usarse para realizar búsquedas sin esquema contra el índice.
Un término representa la existencia de una palabra dentro de un esquema específico. Es decir, si la palabra "Ejecutar" de STEMMed aparece dentro del esquema del usuario y también aparece en el esquema del producto, entonces habrá dos registros de términos para esa palabra, dentro de ese esquema. También se almacena una frecuencia de documento inversa junto con el término para proporcionar un esquema IDF específico que permita las búsquedas contra un esquema específico (estas búsquedas no se verán afectadas por los valores de IDF de todo el índice para las palabras).
Una columna es un campo disponible dentro de un esquema. La columna almacena reglas sobre si los datos que representa se almacenan, si está indexado y su peso que puede usarse para priorizar columnas en consultas (por ejemplo, un título de producto puede tener más peso que una descripción)
Un documento representa una entidad real en un índice, este es el elemento que realmente está indexado y formará la base de los resultados para las consultas.
Un campo es un atributo de un documento que coincide con una columna. Las columnas, documentos y campos actúan como una base de datos típica. Una columna es como una columna de tabla, un documento es como una fila o un registro y un campo es una celda o entrada.
Una ocurrencia representa la existencia de un término (una palabra específica de esquema) dentro de un campo en un documento. Una ocurrencia es una representación única de un término y campo. Junto a una ocurrencia, también almacenamos una frecuencia, que representa el número de veces que el término aparece dentro del campo (que se usa para calcular las puntuaciones más adelante al buscar).
Las posiciones representan que las posiciones reales de los términos dentro de los campos. Si la palabra "ejecutar" (o sus tallos) aparece 3 veces en un campo, habría 3 registros de posición, cada uno marcando la posición de esa ocurrencia dentro del campo correspondiente.
Imagine que tenemos un esquema de "usuario" en nuestro índice. Ese esquema define 2 columnas para cada instancia de usuario, "Nombre" y "Acerca de". Cada columna está almacenada e indexada y ambas tienen un peso de 1. Tenemos 2 usuarios para agregar al índice, [clave: 1, nombre: "Joe Bloggs", "Acerca de": "Joe le gusta Jane"] y [clave: 2, nombre: "Jane Doe", sobre: "Jane ama la fiesta"]. Terminaríamos con la siguiente estructura:
| identificación | nombre |
|---|---|
| 1 | usuario |
| identificación | nombre | almacenado | indexado | peso |
|---|---|---|---|---|
| 1 | nombre | 1 | 1 | 1 |
| 2 | acerca de | 1 | 1 | 1 |
| identificación | palabra |
|---|---|
| 1 | José |
| 2 | blogg |
| 3 | como |
| 4 | jane |
| 5 | gama |
| 6 | amar |
| 7 | a |
| 8 | fiesta |
| identificación | esquema_id | word_id | document_count |
|---|---|---|---|
| 1 | 1 | 1 | 2 |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 2 |
| 4 | 1 | 4 | 3 |
| 5 | 1 | 5 | 1 |
| 6 | 1 | 6 | 1 |
| 7 | 1 | 7 | 1 |
| 8 | 1 | 8 | 1 |
| identificación | esquema_id | llave |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| identificación | document_id | columna_id | valor |
|---|---|---|---|
| 1 | 1 | 1 | Joe bloggs |
| 2 | 1 | 2 | A Joe le gusta Jane |
| 3 | 2 | 1 | Jane Doe |
| 4 | 2 | 2 | A Jane le gusta ir de fiesta |
| identificación | campo_id | Term_id | frecuencia |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 |
| 3 | 2 | 1 | 1 |
| 4 | 2 | 3 | 1 |
| 5 | 2 | 4 | 1 |
| 6 | 3 | 4 | 1 |
| 7 | 3 | 5 | 1 |
| 8 | 4 | 4 | 1 |
| 9 | 4 | 3 | 1 |
| 10 | 4 | 7 | 1 |
| 11 | 4 | 8 | 1 |
| identificación | ocurrencia_id | posición |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 1 |
| 4 | 4 | 2 |
| 5 | 5 | 3 |
| 6 | 6 | 1 |
| 7 | 7 | 2 |
| 8 | 8 | 1 |
| 9 | 9 | 2 |
| 10 | 10 | 3 |
| 11 | 11 | 4 |
Cuando se crea el objeto BLIXT, inicialmente carga todos los objetos de esquema y columna almacenados en la memoria, si los hay. Esto le permite a BLIXT buscar rápidamente un esquema y sus columnas asociadas para validar una solicitud de índice y recopilar rápidamente las restricciones is_indexed e is_stored . en cada columna.
Antes de que pueda la indexación de un documento, se debe definir un esquema con un conjunto de columnas, cada una con sus propias propiedades que especifiquen si los campos que representan deben almacenarse y indexarse. Si ya existe un esquema, esta parte se puede omitir. Si no se proporciona una definición de esquema y no existe dicho esquema, se lanza una excepción.
Se proporciona un documento en forma de un documento indexable, que especifica una clave que el sistema del cliente puede utilizarlo para identificarlo más tarde. Un documento indexable contiene un conjunto de campos. Se proporciona un esquema (o tipo) junto con el documento para que BLIXT pueda colocar el documento en el esquema correcto dentro del índice.
BLIXT comienza a procesar el documento al verificar primero para asegurarse de que no existe en el índice bajo ese esquema. Si existe, se lanza una excepción.
BLIXT agregará un registro de documento y comenzará a procesar los campos del documento. Cada campo se divide en fichas (en la mayoría de los casos, un token es una palabra), y luego cada token se siente (es decir, encontrar la raíz de una palabra, por ejemplo, con un en inglés/portero, la palabra "ejecutar" es el tallo de las palabras "ejecutar", "corredor", "ejecuta", etc.)
Luego se agregan registros de palabras para cada uno de los tokens si ya no existen registros correspondientes, y luego los registros de término se crean bajo el esquema en consecuencia. Los totales de recuento de documentos para el término registros se actualizan para reflejar la adición del nuevo documento.
Se crean registros de ocurrencia para cada combinación de término y campo únicos, lo que indica que el término especificado ocurre dentro del campo específico. La frecuencia (número de veces que el término ocurrió dentro del campo) se almacena junto al registro de ocurrencia. Los datos posicionales también se almacenan en cada registro de ocurrencia que representa cada posición en un campo que ocurrió un término.
Se admiten los siguientes tipos de consultas:
+ que hace que un término sea requerido (y) o un ~ que hace que un término elimine un documento de la consideración (no). Este tipo de consulta forma la base de todas las otras consultas. La búsqueda comienza dividiendo la frase de búsqueda en palabras separadas (tokenización) y luego convirtiendo cada palabra en su forma raíz (derivación). Luego se consulta el índice para encontrar registros de palabras que coinciden con los términos. Usando los registros de palabras y el esquema que estamos interrogando, se extraen los registros de términos. Si alguno de los términos de búsqueda que tenía el operador + adjunto no está presente en los registros de término, entonces se devuelve un conjunto de resultados vacío.
Luego se realiza una consulta para encontrar campos que contengan los términos de la consulta (independientemente del operador) y los documentos asociados con esos campos se devuelven (con sus campos, ocurrencias y posiciones cargadas en consecuencia). Luego, cada documento se analiza y se acepta o se rechaza, si un documento no contiene un término requerido ( + ) o contiene un término eliminado ( ~ ) se rechaza, se aceptan todos los demás documentos. El conjunto de documentos aceptados se devuelve como resultados.
Los siguientes tipos de consultas deben ser compatibles más adelante:
Consulta de un solo término: similar a una consulta de múltiples plazos, los documentos se califican contra un solo término.
Consulta de frase completa: similar a una consulta de múltiples plazos, pero solo se permiten documentos que contienen cada término en el orden correcto.
También está destinado a implementar el análisis de consultas para que una cadena de búsqueda de entrada se pueda convertir al tipo de consulta correcto antes de realizar la búsqueda.
Estas son mejoras destinadas al futuro.
Implemente un caché agnóstico de almacenamiento (redis, memcached, sistema de archivos, etc.) que podemos usar para mejorar el rendimiento de la búsqueda. Hay una serie de casos de uso para un caché en este proyecto:
Nota: Para implementar algunas de las características anteriores, potencialmente necesitaríamos utilizar un identificador de sesión único para que se retire y reciba del usuario para garantizar que las búsquedas en caché solo sean válidas para ese usuario y para evitar que esos objetos almacenados en caché se borraran. Este es definitivamente el caso al almacenar en caché un conjunto completo de resultados de búsqueda para permitir que el usuario pagine. También podría valer la pena almacenar en caché las versiones que no se consideran específicas de la sesión para permitir a muchos usuarios que buscan lo mismo ver los mismos resultados de búsqueda rápidamente.
Durante el proceso de indexación, podemos usar una tabla adicional para almacenar una asignación de términos a los documentos, lo que nos indicará en qué documentos aparece un término dado. Esto nos permitiría omitir gran parte del proceso de tratar de determinar los ID de documentos candidatos simplemente tomar la lista de documentos que aparece un término para permitirnos generar rápidamente (o en el caso de los términos prohibidos, reducir el número de documentos candidatos.