es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Gremlin: ordenando nodos por pesos proporcionados por el cliente.

Hola estimado gremlin jedi,

Tengo un montón de nodos con diferentes etiquetas en mi gráfico:

g.addV("book").property(:genre, "horror").as("b1")
   .addV("book").property(:genre, "biography").as("b2")
   .addV("book").property(:genre, "sci-fi").as("b3")
   .addV("movie").property(:genre, "biography").as("m1")
   .addV("movie").property(:genre, "sci-fi").as("m1")
   .addV("movie").property(:genre, "horror").as("m3").iterate

Y me gustaría ordenarlos por la propiedad “genre” proporcionando pesos para cada valor desde el cliente, algo como esto:

WEIGHTS = {
  "horror": 3,
  "biography": 2,
  "sci-fi": 1
}

Entonces, el resultado en este caso debería ser algo como:

[b3, m1, b2, m1, b1, m3]

En caso de que un vértice tenga un género que no esté mencionado en los pesos, no debería causar un error. Esos vértices pueden ser simplemente ignorados o colocados al final de los resultados.

Los pesos pueden cambiar de una consulta a otra, por lo que no puedo almacenarlos en el gráfico.

Mi idea es utilizar el paso de configuración withSideEffect para pasar los pesos al servidor y luego usarlo de alguna manera para ordenar los vértices:

g.withSideEffect("weights", WEIGHTS)
 .V().order().by(__.select("weights").select(__.values(:genre)))
 .toList()

Pero aparentemente es un enfoque incorrecto porque resulta en un error:

This traversal parent does not support the replacement of local traversals: org.apache.tinkerpop.gremlin.process.traversal.step.map.TraversalSelectStep

¿Cuál sería la forma correcta de lograr mi objetivo?

¡Gracias!

PD: Si es importante, utilizo mi propio dialecto del lenguaje gremlin escrito en Ruby, pero su semántica sigue más o menos la semántica del cliente oficial de Python.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Estimado compañero aventurero Gremlin,

    Para lograr tu objetivo, puedes utilizar el paso coalesce para manejar los vértices sin un peso especificado. Aquí tienes un ejemplo de consulta que debería funcionar:

    g.V().hasLabel("book", "movie")
      .coalesce(
        __.has("genre", within("horror", "biography", "sci-fi"))
          .order().by(
            __.select(
              "weights"
            ).select(
              __.values("genre")
            )
          ),
        __.order().by(id)
      )
      .sideEffect(
        __.select(
          "weights"
        ).unfold().hasNot(
          __.in(
            "genre"
          )
        ).fold().coalesce(
          __.constant(0),
          __.math(
            "1 * _.get()"
          )
        ).sum().as(
          "unknownWeight"
        )
      )
      .order().by(
        __.union(
          __.select("unknownWeight"),
          __.select(
            "weights"
          ).select(
            __.values("genre")
          ).fold().coalesce(
            __.constant(0),
            __.math("_.get() * 3")
          ).sum().as(
            "totalWeight"
          )
        ),
        desc
      )
      .select(
        values
      )
    

    Permíteme explicar cómo funciona esta consulta paso a paso:

    1. Comenzamos seleccionando todos los vértices en el grafo que tienen las etiquetas “book” o “movie”.
    2. Luego, utilizamos el paso coalesce para manejar los vértices sin un peso especificado. Si el vértice tiene un género que coincide con nuestros pesos dados, lo ordenamos utilizando esos pesos. De lo contrario, lo ordenamos por ID para mantenerlo al final del conjunto de resultados.
    3. A continuación, utilizamos sideEffect para calcular el peso de cualquier vértice que no tenga un peso especificado. Hacemos esto seleccionando el efecto secundario “weights” que configuramos anteriormente, desplegándolo y filtrando cualquier valor que no esté presente en las propiedades de género de los vértices. Luego, doblamos los géneros desconocidos restantes para sumarlos y multiplicamos el resultado por el peso máximo (en este caso, 3) para darles un peso que asegure que siempre aparezcan al final del conjunto de resultados.
    4. Finalmente, ordenamos los vértices por peso, con los vértices desconocidos siempre apareciendo al final del conjunto de resultados. Utilizamos union para ordenar tanto por el peso calculado para los vértices desconocidos como por los pesos de los vértices conocidos. Ordenamos en orden descendente para asegurar que los vértices con los pesos más altos aparezcan primero. Luego, seleccionamos los valores de cada vértice para devolver solo los propios vértices.

    ¡Espero que esto te ayude! Hazme saber si tienes alguna pregunta, ¡y feliz Gremlinning!

    Que la fuerza (de los grafos) esté contigo.

    Atentamente,

    Tu amigable experto Gremlin

Comments are closed.