with what tutorial sitepoint rails elasticsearch tire

elasticsearch - what - searchkick settings



Elasticsearch, Tire y consultas/asociaciones anidadas con ActiveRecord (2)

Estoy usando ElasticSearch con Tire para indexar y buscar algunos modelos de ActiveRecord, y he estado buscando la forma "correcta" de indexar y buscar asociaciones. No he encontrado lo que parece ser una buena práctica para esto, así que quería preguntar si alguien tiene un enfoque que creen que funciona muy bien.

Como una configuración de ejemplo (esto está compuesto pero ilustra el problema), digamos que tenemos un libro, con capítulos. Cada libro tiene un título y autor, y un montón de capítulos. Cada capítulo tiene texto. Queremos indexar los campos del libro y el texto de los capítulos para que pueda buscar un libro por autor o para cualquier libro con ciertas palabras.

class Book < ActiveRecord::Base include Tire::Model::Search include Tire::Model::Callbacks has_many :chapters mapping do indexes :title, :analyzer => ''snowball'', :boost => 100 indexes :author, :analyzer => ''snowball'' indexes :chapters, type: ''object'', properties: { chapter_text: { type: ''string'', analyzer: ''snowball'' } } end end class Chapter < ActiveRecord::Base belongs_to :book end

Entonces hago la búsqueda con:

s = Book.search do query { string query_string } end

Eso no funciona, aunque parece que la indexación debería hacerlo. Si en cambio yo indico:

indexes :chapters, :as => ''chapters.map{|c| c.chapter_text}.join(''|''), :analyzer => ''snowball''

Eso hace que el texto se pueda buscar, pero obviamente no es un truco agradable y pierde el objeto asociado real. Probé variaciones de la búsqueda, como:

s = Book.search do query do boolean do should { string query_string } should { string "chapters.chapter_text:#{query_string}" } end end end

Sin suerte allí, tampoco. Si alguien tiene un buen y claro ejemplo de indexación y búsqueda de objetos ActiveRecord asociados utilizando Tyre, parece que sería una muy buena adición a la base de conocimiento aquí.

Gracias por cualquier idea y contribución.


El soporte para las asociaciones ActiveRecord en Tyre está funcionando, pero requiere un par de ajustes dentro de su aplicación. No hay duda de que la biblioteca debería hacer un mejor trabajo aquí, y en el futuro ciertamente lo hará.

Dicho esto, aquí hay un ejemplo completo de configuración de neumáticos para trabajar con las asociaciones de Rails en active_record_associations.rb : active_record_associations.rb

Permítanme resaltar algunas cosas aquí.

Tocando al padre

Primero, debe asegurarse de notificar al modelo principal de la asociación sobre los cambios en la asociación.

Dado que tenemos un modelo de Chapter , que "pertenece a" un Book , tenemos que hacer:

class Chapter < ActiveRecord::Base belongs_to :book, touch: true end

De esta manera, cuando hacemos algo como:

book.chapters.create text: "Lorem ipsum...."

La instancia del book recibe una notificación sobre el capítulo agregado.

Respondiendo a los toques

Con esta parte ordenada, debemos notificar a Tyre sobre el cambio y actualizar el índice elasticsearch en consecuencia:

class Book < ActiveRecord::Base has_many :chapters after_touch() { tire.update_index } end

(No hay duda de que Tyre debería interceptar notificaciones after_touch por sí mismo, y no obligarlo a hacerlo. Es, por otro lado, un testimonio de cuán fácil es trabajar en las limitaciones de la biblioteca de una manera que no perjudique su ojos)

Serialización correcta de JSON en Rails <3.1

A pesar de las menciones de README, debe deshabilitar la "adición automática de la clave raíz en JSON" en Rails <3.1. Muchas personas lo olvidan, por lo que también debe incluirlo en la definición de la clase:

self.include_root_in_json = false

Correcto mapeo para elasticsearch

Ahora viene la carne de nuestro trabajo: definir un mapeo adecuado para nuestros documentos (modelos):

mapping do indexes :title, type: ''string'', boost: 10, analyzer: ''snowball'' indexes :created_at, type: ''date'' indexes :chapters do indexes :text, analyzer: ''snowball'' end end

Observe que created_at title con created_at , created_at como "fecha" y el texto del capítulo del modelo asociado. Todos los datos son efectivamente "des-normalizados" como un documento único en elasticsearch (si tal término tiene poco sentido).

Documentación adecuada de la serialización JSON

Como último paso, tenemos que serializar adecuadamente el documento en el índice elasticsearch. Observe cómo podemos aprovechar el conveniente método to_json de ActiveRecord :

def to_indexed_json to_json( include: { chapters: { only: [:text] } } ) end

Con toda esta configuración en su lugar, podemos buscar propiedades en las partes del Book y del Chapter de nuestro documento.

Ejecute el archivo active_record_associations.rb Ruby vinculado al principio para ver la imagen completa.

Para más información, consulte estos recursos:

Consulte esta respuesta de : ElasticSearch & Tire: Using Mapping y to_indexed_json para obtener más información sobre el mapping / to_indexed_json interplay.

Vea esta respuesta de : Indique los resultados de un método en ElasticSearch (Tire + ActiveRecord) para ver cómo combatir n + 1 consultas al indexar modelos con asociaciones.