Tengo una columna jsonb llamada lms_data con una estructura de datos hash dentro. Estoy tratando de encontrar elementos que coincidan con una serie de identificadores. Esta consulta funciona y devuelve el resultado correcto:
CoursesProgram .joins(:course) .where(program_id: 12) .where( "courses.lms_data->>'_id' IN ('604d26cadb238f542f2fa', '604541eb0ff9d7b28828c')")REGISTRO SQL:
CoursesProgram Load (0.5ms) SELECT "courses_programs".* FROM "courses_programs" INNER JOIN "courses" ON "courses"."id" = "courses_programs"."course_id" WHERE "courses_programs"."program_id" = $1 AND (courses.lms_data->>'_id' IN ('604d26cadb61e238f542f2fa', '604541eb0ff9d8387b28828c')) [["program_id", 12]Sin embargo, cuando trato de pasar una variable como la matriz de ID:
CoursesProgram .joins(:course) .where(program_id: 12) .where( "courses.lms_data->'_id' IN (?)", ["604d26cadb61e238f542f2fa", "604541eb0ff9d8387b28828c"])No obtengo ningún resultado y obtengo dos consultas realizadas en los registros...
CoursesProgram Load (16.6ms) SELECT "courses_programs".* FROM "courses_programs" INNER JOIN "courses" ON "courses"."id" = "courses_programs"."course_id" WHERE "courses_programs"."program_id" = $1 AND (courses.lms_data->'_id' IN ('604d26cadb61e238f542f2fa','604541eb0ff9d8387b28828c')) [["program_id", 12]] CoursesProgram Load (0.8ms) SELECT "courses_programs".* FROM "courses_programs" INNER JOIN "courses" ON "courses"."id" = "courses_programs"."course_id" WHERE "courses_programs"."program_id" = $1 AND (courses.lms_data->'_id' IN ('604d26cadb61e238f542f2fa','604541eb0ff9d8387b28828c')) LIMIT $2 [["program_id", 12], ["LIMIT", 11]]No puedo envolver mi cabeza alrededor de este. Las consultas realizadas en ambos casos parecen ser las mismas. ¿Por qué uno funciona y el otro no? y ¿por qué en el segundo caso la consulta se realiza dos veces?
El signo de interrogación es su propio operador en el conjunto de funciones de consulta json de postgres (es decir, ¿existe esto?). ActiveRecord intenta hacer lo que cree que desea, pero existen limitaciones con las expectativas.
Solución. No lo uses. Desde el ? puede causar problemas con la consulta json de postgres, en su lugar uso la sustitución con nombre.
de la documentación de postgres:
?| text[] Do any of these array strings exist as top-level keys? '{"a":1, "b":2, "c":3}'::jsonb ?| array['b', 'c'] Así que primero usamos el ?| operador postgres json para buscar ANY en los valores de lms_data.
Y en segundo lugar, le decimos a postgres que usaremos una matriz con la función de matriz de postgres array[:named_substitution]
Y, por último, después de , al final de la consulta de postgres, agregue su subvariable nombrada (en este caso usé: ids) y su matriz.
CoursesProgram .joins(:course) .where(program_id: 12) .where( "courses.lms_data->>'_id' ?| array[:ids]", ids: ['604d26cadb238f542f2fa', '604541eb0ff9d7b28828c'])