Obtuve un error extraño al usar FaunaDB con Node.js ejecutándose en una función Netlify.
Estoy construyendo una prueba de concepto rápida e inicialmente todo funcionó bien. Tuve una consulta Crear que se veía así:
const faunadb = require('faunadb'); const q = faunadb.query; const CreateFarm = (data) => ( q.Create( q.Collection('farms'), { data }, ) ); Como dije, todo aquí funciona como se esperaba. El problema comenzó cuando traté de comenzar a normalizar los datos que envía FaunaDB. Específicamente, quiero fusionar la identificación generada por Fauna en el objeto data y enviar solo eso de regreso sin ninguno de los otros metadatos.
Ya lo estoy haciendo con otros recursos, así que escribí una consulta auxiliar y la incorporé:
const faunadb = require('faunadb'); const q = faunadb.query; const Normalize = (resource) => ( q.Merge( q.Select(['data'], resource), { id: q.Select(['ref', 'id'], resource) }, ) ); const CreateFarm = (data) => ( Normalize( q.Create( q.Collection('farms'), { data }, ), ) ); Esta función Normalize funciona como se esperaba en cualquier otro lugar. Construye el objeto fusionado correcto con una identificación sin efectos secundarios extraños. Sin embargo, cuando se usa con CreateFarm como se indicó anteriormente, termino con dos granjas idénticas en la base de datos.
He pasado mucho tiempo mirando el resto de la aplicación. Definitivamente, solo ingresa una solicitud POST , y CreateFarm definitivamente solo se llama una vez. Mi mejor teoría fue que, dado que Merge copia el primer recurso que se le pasó, de alguna manera se llama a Create dos veces en la base de datos. Pero reordenar la llamada Merge no cambia nada. Incluso he intentado pasar un objeto vacío primero, pero siempre termino con dos objetos idénticos creados al final.
Su ayudante crea una consulta FQL con dos expresiones Create separadas. Cada uno es evaluado y crea un nuevo Documento. Esto no está relacionado con la función Merge .
Merge( Select(['data'], Create( Collection('farms'), { data }, )), { id: Select(['ref', 'id'], Create( Collection('farms'), { data }, )) }, ) Use Let para crear el documento, luego Update con la identificación. Tenga en cuenta que esto aumenta la cantidad de operaciones de escritura requeridas para su aplicación. Básicamente duplicará el costo de crear Documentos. Pero para lo que está tratando de hacer, esta es la forma de hacerlo.
Let( { newDoc: Create(q.Collection("farms"), { data }), id: Select(["ref", "id"], Var("newDoc")), data: Select(["data"], Var("newDoc")) }, Update( Select(["ref"], Var("newDoc")), { data: Merge( Var("data"), { id: Var("id") } ) } ) )No está claro por qué podría necesitar hacer esto. Los índices se pueden crear en el valor de referencia en sí mismos. Si su cliente recibe una Ref, entonces eso se puede pasar directamente a las consultas posteriores. En mi experiencia, si necesita el valor de identificación simple directamente en una aplicación, transforme el documento lo más cerca posible de ese punto en la aplicación (como usar identificaciones como claves para una matriz de componentes web).
Incluso hay una ligera ventaja informática al usar valores de referencia en lugar de reconstruir expresiones de referencia a partir de un nombre e ID de colección. La expresión
Ref(Collection("farms"), "1234")cuenta como 2 funciones FQL para los costos de Cómputo, pero la reutilización del valor Ref devuelto por las consultas es gratuita.
Al trabajar con GraphQL, el campo _id se abstrae porque trabajar con tipos de documentos en GraphQL sería bastante horrible. Sin embargo, la mejor práctica para las consultas FQL sería utilizar las referencias directamente tanto como sea posible.
¡Sin embargo, no me dejes hablar en términos absolutos! Generalmente creo que hay una razón para cualquier cosa. Si cree que realmente necesita duplicar la ID en los datos de Documentos, entonces me interesaría un comentario sobre por qué.