2010-03-12 18 views
8

Estoy creando una aplicación que necesita búsquedas inversas. Con esto, quiero decir que los usuarios de la aplicación ingresarán los parámetros de búsqueda y los guardarán; luego, cuando se ingresan nuevos objetos en el sistema, si coinciden con los parámetros de búsqueda existentes que un usuario ha guardado, se enviará una notificación, etc.¿Mejores prácticas de búsqueda inversa?

Estoy teniendo dificultades para encontrar soluciones para este tipo de problema .

estoy usando Django y pensando en la construcción de las búsquedas y decapado usando objetos Q como se indica aquí: http://www.djangozen.com/blog/the-power-of-q

La forma en que lo veo, cuando se introduce un nuevo objeto en la base de datos, voy a tener que cargar cada consulta guardada del archivo db y de alguna manera ejecutarla contra este nuevo objeto para ver si coincide con esa consulta de búsqueda ... Esto no parece ideal. ¿Alguien ha abordado ese problema antes?

Respuesta

4

En el nivel de la base de datos, muchas bases de datos ofrecen 'disparadores'.

Otro enfoque es tener trabajos temporizados que periódicamente recuperan todos los elementos de la base de datos que tienen una fecha de última modificación desde la última ejecución; luego estos se filtran y se emiten alertas. Quizás pueda poner parte del filtrado en la declaración de consulta en la base de datos. Sin embargo, esto es un poco más complicado si las notificaciones deben enviarse si los artículos obtienen eliminado.

También puede colocar desencadenantes manualmente en el código que envía datos a la base de datos, que es quizás más flexible y ciertamente no se basa en características específicas de la base de datos.

Una buena manera para que los desencadenantes y las alertas se comuniquen es a través de colas de mensajes: las colas como RabbitMQ y otras implementaciones de AMQP se escalarán con su sitio.

4

La cantidad de esfuerzo que utiliza para resolver este problema está directamente relacionada con el número de consultas almacenadas que está tratando. Hace

más de 20 años manejamos consultas almacenadas tratándolos como minidocs y la indexación de ellos basados ​​en la totalidad de la debe tener y pueden tener términos. Se utilizó una lista de términos de un nuevo documento como un tipo de consulta en contra de esta "base de datos de consultas" y que creó una lista de posiblemente búsquedas interesantes para ejecutar, y luego solo esas búsquedas se ejecutaron contra los nuevos documentos. Esto puede sonar intrincado, pero cuando hay más de consultas almacenadas (digamos entre 10,000 y 1,000,000 o más) y tiene un lenguaje de consulta complejo que admite un híbrido de búsqueda booleana y basada en similitudes, redujo sustancialmente la número que tuvimos que ejecutar como consultas completas, a menudo no más de 10 o 15 consultas.

Una cosa que ayudó fue que teníamos el control del horizontal and the vertical de todo el asunto. Usamos nuestro analizador de consultas para construir un árbol de análisis sintáctico y que se usó para construir la lista de términos must/may have bajo los cuales indexamos la consulta. Advertimos al cliente que no utilice ciertos tipos de comodines en las consultas almacenadas porque podría causar una explosión en el número de consultas seleccionadas.

Actualización para comentario:

Respuesta corta: no sé a ciencia cierta.

Respuesta más larga: Estábamos trabajando con un motor de búsqueda de texto personalizado y parte de su sintaxis de consulta permitía dividir la colección de documentos de cierto modo de manera muy eficiente, con especial énfasis en date_added. Jugamos muchos juegos porque estábamos ingiriendo entre 4 y 10 millones de nuevos documentos al día y ejecutándolos contra hasta 1.000.000 de consultas almacenadas en un DEC Alphas con 64 MB de memoria principal. (Esto fue a finales de los 80/principios de los 90.)

supongo que el filtrado en algo equivalente a date_added podría hacerse utilizado en combinación de la fecha de la última vez que se ejecutó sus consultas, o tal vez el más alto id en último tiempo de ejecución de la consulta. Si necesita volver a ejecutar las consultas en un registro modificado, puede usar su id como parte de la consulta.

para que consiga más específica, vas a tener que obtener una gran cantidad más específica sobre exactamente qué problema que está tratando de resolver y la escala de la solución que usted está tratando de lograr.

+0

Su concepto de términos de "debe tener" y "puede tener" tiene mucho sentido para reducir el número de búsquedas guardadas que deben ejecutarse contra documentos nuevos. La segunda parte de la pregunta es más relacionada con django, digamos que tienes una instancia de modelo, ¿cómo exactamente se ejecutaría un filtro/consulta solo contra esta instancia para determinar una coincidencia booleana? – edub

+0

+1, he estado pensando en soluciones para este problema y obtuve la misma solución. Aunque todavía estoy buscando otras posibles soluciones, este diseño es mucho mejor que revisar cada consulta almacenada para verificar si coincide con una nueva entrada. Gracias por publicar. –

1

Si almacenó el tipo (s) de objeto (s) involucrados en cada búsqueda almacenada como generic relation, puede agregar signal a todos los objetos implicados. Cuando la señal se activa, busca solo las búsquedas que involucran su tipo de objeto y las ejecuta. Es probable que esto siga teniendo problemas de escalado si tienes toneladas de escrituras en el DB y muchas búsquedas guardadas, pero sería un enfoque directo de Django.

+0

Pensando en ello, si lo hizo como una tarea cron o si usó Celery/similar para procesar nuevos elementos fuera del proceso de guardado, no tendría que preocuparse tanto por el escalado. – Tom