2012-05-21 9 views
20

Estoy tratando de crear una búsqueda de negocios con características sociales usando ElasticSearch. Tengo un directorio de negocios, y los usuarios pueden interactuar con esos negocios de diferentes maneras: revisándolos, registrándolos, etc.¿Cómo se puede usar ElasticSearch para implementar la búsqueda social?

Cuando un usuario busca una empresa, me gustaría poder mostrarle negocios con los que sus amigos han interactuado en la parte superior de los resultados (o filtros basados ​​en esas interacciones). ¿Cuál es la mejor manera de configurar mi índice para lograr esto?

se me ocurre tiene algunas soluciones posibles, pero soy un principiante con ES y no estoy seguro de lo que va a causar problemas:

  1. que podría utilizar múltiples tennancy y crear una separada índice para cada usuario. Lo descarté porque la cantidad de usuarios es mucho mayor que la cantidad de negocios o la cantidad de contenido específico del usuario.

  2. Podría agregar una lista de pares de usuario/puntaje para cada negocio indexado. Cada usuario que haya interactuado con la empresa estaría allí, y el puntaje representaría la cantidad de interacción que tuvieron con la empresa (esto es suficiente para mis propósitos de filtrado/clasificación). Cada vez que interactúan con el negocio, actualizaría el puntaje en el índice. El problema con esto es que solo me importa la actividad de mis amigos, por lo que tendría que encontrar la manera de tener en cuenta quiénes son mis amigos al crear una puntuación compuesta para el negocio. No sé cómo hacer esto en ES.

  3. Podría crear un esquema similar, pero en lugar de llevar la puntuación de mis interacciones con una empresa, la puntuación reflejaría las interacciones de mis amigos con la empresa. Esto elimina la necesidad de modelar mi gráfico social en ElasticSearch, pero significa que cada vez que una persona interactúa con un negocio, necesitaría actualizar todos los puntajes de sus amigos. También significaría que la lista de pares de usuario/puntaje para cada negocio sería mayor, ya que deberá incluir a cualquier persona que tenga un amigo que haya interactuado con la empresa.

  4. La solución final en la que puedo pensar es realizar un seguimiento de cada interacción individual que le sucede a una empresa y agregarla al documento comercial en ES. Esto no me parece realista: combina los problemas de las otras soluciones. Pero es probablemente el enfoque más directo en términos de mantener el índice actualizado.

¡Gracias por su ayuda!

+1

Me enfrento a un problema similar: ¿te importa compartir cómo terminaste haciéndolo? – EugeneMi

Respuesta

8

Estoy votando por una # 2 modificada.

En lugar de almacenar cada par de usuario/puntaje dentro del propio documento comercial, crearía una relación Padre/Hijo. Esto le permite actualizar el puntaje del niño (las puntuaciones de los usuarios) sin tener que volver a indexar todo el documento comercial (y todos los demás puntajes de los usuarios).

Mira lo que para una gran matriz tutorial/los niños son a mitad de camino hacia abajo: http://www.spacevatican.org/2012/6/3/fun-with-elasticsearch-s-children-and-nested-documents/

A continuación, se puede utilizar un has_child filter o top_children query para encontrar sólo los negocios que sus amigos tienen puntuaciones para. Hay algunas advertencias sobre el pedido de documentos para niños, pero está cubierto por ese tutorial, así que asegúrese de leer hasta el final.

Luego solo realizaría una consulta normal para todas las búsquedas clasificadas "no sociales".

Alternativamente, podría agrupar todo junto y agregar aumentos a los partidos que sus amigos han marcado, para que todo tenga el rango adecuado. Puede ser más fácil realizar dos consultas y combinarlas tú mismo.

5

Hay otra serie de soluciones que tienen la ventaja de ser extremadamente rápidas (es decir, aprovechar lo que ES es mejor), pero son terribles para cualquiera que sepa siquiera lo primero sobre el diseño de sistemas de almacenamiento/recuperación de datos.

Si su índice de 'negocio' es más pequeño que su índice de 'usuario' (es decir, 10.000 biz, 1.000.000 usuarios)

  1. crear 2 índices: usuario y negocios.
  2. El índice comercial debe tener un campo 'array' que contenga los identificadores de cada usuario que alguna vez haya "interactuado" con él (es decir, "usuarios: 1,4,23,26,127,8678")
  3. El índice de usuario debería tener un campo de matriz anidada con ID de empresa y opiniones, confirmaciones, etc en un objeto anidado con información de metadatos (es decir, "business_id: 1233, Grado: 7,5, confirmaciones: 21")

Cuando se busca un negocio, hacer una consulta de cadena rápida o consulta de filtro con los id. de amigos del usuario (por supuesto, en contra) del índice de negocios. El tf-idf debe filtrar automáticamente las empresas que más interactuaron con tus amigos a la cima. Si necesita más información, simplemente presione el índice de usuario para obtener los metadatos de cada uno de sus amigos (calificación, registros, etc.). Esto debería ser más rápido y super eficiente, porque ES es absolutamente fantástico para unir matrices como términos individuales. ¡Eso es lo que es para ti!

Si su índice de "negocios" es significativamente mayor que su índice de "usuario", invierta el patrón ... poniendo una matriz indexada de business_ids con la que un usuario ha interactuado en el índice de usuario.

+0

Soy bastante nuevo con ES, pero cuando creas el índice de usuario, ¿no obtienes el índice de usuario de forma gratuita? Básicamente, el índice Business es el índice inverso de para el campo business_id en el índice de usuario – EugeneMi

3

Simplemente spitballing aquí, pero creo que me gustaría Utilizar una base de datos de gráficos como Neo4J, donde sería trivial hacer una consulta como "empresas que mis amigos han registrado" y consultar tanto esa base de datos y elasticsearch en el al mismo tiempo y resultados de retorno de su base de datos de gráficos primero. O bien, podría obtener los resultados de esa consulta de gráficos y hacer coincidir los resultados en elasticsearch (hacer coincidir los identificadores) y luego aplicar un impulso de tiempo de consulta a los resultados de búsqueda elásticos para que floten en la parte superior de los resultados devueltos.

1

Solr puede hacer esto con el operador GraphQuery.

https://issues.apache.org/jira/browse/SOLR-7543

Se le permite poner los documentos en el índice que contienen un campo para el "node_id" y un campo (varios valores) para el "edge_id"

Hay algunas maneras de estructurar esta :

  1. Puede tener un documento de usuario con una lista de id. De amigos en él.O
  2. Puede tener una tabla separada que sea una tabla de enlaces que vincule los registros de los usuarios.

Para el caso 1: Indique un documento para cada usuario en el sistema con un campo que contenga el "user_id" y otro campo que contenga "friend_ids".

En ese punto para hacer una búsqueda de todos los amigos del usuario 555 sería:

{!graph from="user_id" to="friend_ids" maxDepth=1}user_id:555 

Para encontrar amigos de los amigos del usuario

{!graph from="user_id" to="friend_ids" maxDepth=2}user_id:555 

Si tiene otros campos de metadatos en el registros de usuario como un campo de ubicación, podría agregar eso como un filtro transversal para encontrar a mis amigos que viven en Boston. Este filtro transversal se aplica a cada salto.

{!graph from="user_id" to="friend_ids" maxDepth=2 traversalFilter="location:Boston"}user_id:555 

La consulta anterior encontraría a los amigos que viven en Boston que son amigos del Usuario 555 que viven en Boston.

Cuestiones relacionadas