{"componentChunkName":"component---src-templates-blog-post-js","path":"/campos-unicos-en-firestore/","result":{"data":{"site":{"siteMetadata":{"title":"El Blog de Nessy"}},"markdownRemark":{"id":"980332af-7603-535a-8814-7a6f4727c1a0","excerpt":"Imagina que tienes que guardar un campo de RUT de pacientes en Firestore y que además tienes que preocuparte de no duplicarlos. ¿Cómo lo haces? Firestore no…","html":"<p>Imagina que tienes que guardar un campo de RUT de pacientes en Firestore y que además tienes que preocuparte de no duplicarlos. ¿Cómo lo haces?</p>\n<p>Firestore no tiene una forma nativa para guardar campos únicos, así que tenemos que usar técnicas para lograrlo.</p>\n<p>En este post, veremos una técnica para guardar campos únicos, que podría ser usada para no duplicar registros en base al <a href=\"https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario\">RUT</a>.</p>\n<p>Nota: El RUT es un número único implantado en Chile, que se usa como identificación tributaria. En registros clínicos, se suele usar para identificar al paciente de forma inequívoca.</p>\n<h2>Meta</h2>\n<p>La meta de este artículo es mostrarte un paso a paso de cómo lograr guardar valores únicos en un documento de firestore.</p>\n<p>Para el resto del artículo, consideraremos que existe una colección de pacientes (<code class=\"language-text\">patients</code>) y que queremos hacer que el campo rut sea único.</p>\n<h2>¿Qué es un campo único?</h2>\n<p>Un campo único es un dato particular que debe ser único entre todos tus registros.</p>\n<p>Estos van a depender de la aplicación que estés construyendo, pero algunos ejemplos que suelen ser únicos: identificadores, RUT de pacientes y correo electrónicos.</p>\n<h2>¿Por qué guardar un campo único en Firestore no es fácil?</h2>\n<p><a href=\"https://firebase.google.com/products/firestore\">Firestore</a> no tiene la funcionalidad para guardar un campo único. No es como otros motores de base de datos donde puedes decir “mira, quiero que la propiedad rut sea única para todos estos registros”.</p>\n<p>Para lograrlo, hay que usar distintas técnicas, y va a depender de tu caso particular.</p>\n<h2>¿Cómo podemos guardar un campo único?</h2>\n<p>En este artículo veremos dos formas, las cuales van a depender de tu situación particular.</p>\n<p>La primera es la más sencilla: <strong>haz que el campo único sea el identificador de tu documento en Firestore</strong>. Te conviene esta solución cuando no puede existir un registro sin el dato.</p>\n<p>La segunda es más complicada: <strong>crea una colección para tu campo único y controla la escritura mediante reglas de seguridad</strong>. Te conviene esta solución cuando no puedes usar la primera.</p>\n<h2>Alternativa #1: Haz que el campo único sea el identificador de tu documento en Firestore</h2>\n<p>Si tienes registros de pacientes y por requerimientos siempre existirán pacientes con RUT, puedes optar por esta alternativa.</p>\n<p>Cuando crees pacientes, en vez de usar la función <code class=\"language-text\">add()</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Tendrás que hacerlo con <code class=\"language-text\">doc()</code> y <code class=\"language-text\">set()</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Luego te recomiendo agregar en <a href=\"https://firebase.google.com/docs/firestore/security/get-started\">Reglas de Seguridad</a> que el ID del documento sea igual al RUT:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">match /patients/{patientId} {\n  allow create: if patientId == request.resource.data.rut;\n}</code></pre></div>\n<p>Puedes validar también que <code class=\"language-text\">patientId</code> <em>parezca</em> un rut válido (mediante una <a href=\"https://firebase.google.com/docs/reference/security/database/regex\">expresión regular</a>).</p>\n<p>Nota: para validar el dígito verificador, tendrías que hacerlo en una <a href=\"https://firebase.google.com/products/functions\">Cloud Function</a>, ya que en <a href=\"https://firebase.google.com/docs/firestore/security/get-started\">Firestore Security Rules</a> no puedes usar loops (aunque quizás es posible hacerlo sin loops 🙃).</p>\n<h2>Alternativa #2: Crea una colección para tu campo único y controla la escritura mediante reglas de seguridad</h2>\n<p>Si no puedes optar por la solución anterior, tendrás que hacer algo más complicado.</p>\n<p>La idea es tener una colección aparte, que sea como un mapa entre tu campo único y el ID del documento que lo tiene. Luego agregar validaciones mediante reglas de seguridad. A esta colección la llamaré <code class=\"language-text\">identifiers</code>.</p>\n<p>El resultado final será que para cada registro de paciente, también existirá un registro en la colección de identificadores. Por ejemplo:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6893f556191b99070fb4efc1f529e053/05244/Screen_Shot_2022-07-06_at_13.54.32.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 28.48101265822785%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAAAtUlEQVQY04WQ6wqDMAyF+/7vKIq/ButF3Wzt9SwJKIVtGPga0qQnSdW6rojxQErpwnuPfd+htYa1FlzjnBM4Zr8sy3XXox4uQm8JIWbUUlBrRWsNdMAfGfaV8dwy3qGgUa5QTQ/X9yhtLLRxMOS5q4iJNYRUqVmRhjkXyd2heAVDqxljBO4icpSstSGmLF8QCJ7ozP0zxXuz0PlfveCvh7cTTtMEZhgGYRxHied5pjXzl8jdhB8P9NPEcBKnwgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Paciente con ID = 5dedf…\"\n        title=\"Paciente con ID = 5dedf…\"\n        src=\"/static/6893f556191b99070fb4efc1f529e053/f058b/Screen_Shot_2022-07-06_at_13.54.32.png\"\n        srcset=\"/static/6893f556191b99070fb4efc1f529e053/c26ae/Screen_Shot_2022-07-06_at_13.54.32.png 158w,\n/static/6893f556191b99070fb4efc1f529e053/6bdcf/Screen_Shot_2022-07-06_at_13.54.32.png 315w,\n/static/6893f556191b99070fb4efc1f529e053/f058b/Screen_Shot_2022-07-06_at_13.54.32.png 630w,\n/static/6893f556191b99070fb4efc1f529e053/40601/Screen_Shot_2022-07-06_at_13.54.32.png 945w,\n/static/6893f556191b99070fb4efc1f529e053/78612/Screen_Shot_2022-07-06_at_13.54.32.png 1260w,\n/static/6893f556191b99070fb4efc1f529e053/05244/Screen_Shot_2022-07-06_at_13.54.32.png 1752w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p class=\"figure-caption\">Paciente con ID = 5dedf…</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/ff99d3872bc64caa7bbc2f92e2f868d7/bcec6/Screen_Shot_2022-07-06_at_13.52.58.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 20.253164556962027%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsSAAALEgHS3X78AAAAkElEQVQY042Q2QpDIQxE/f8/dUWtpi6xU2O5fSlcKhwmCyQTlXUOxnqUSuh9bPqh1ooYI5z3eJQKerZTb639cNWJCKqNBZcnQpkYY2Ixgzdrra2fnkkM6i/881QpBcZoaK3ht5sQwkFi2ZyIEesEz/l1f4cSm9bawzVQVJh7CLM47+ecnDNSSucrBImvXFT6b7aENiaJ2YZNAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Identificador con ID = 1111111-1, y patientId = 5dedf…\"\n        title=\"Identificador con ID = 1111111-1, y patientId = 5dedf…\"\n        src=\"/static/ff99d3872bc64caa7bbc2f92e2f868d7/f058b/Screen_Shot_2022-07-06_at_13.52.58.png\"\n        srcset=\"/static/ff99d3872bc64caa7bbc2f92e2f868d7/c26ae/Screen_Shot_2022-07-06_at_13.52.58.png 158w,\n/static/ff99d3872bc64caa7bbc2f92e2f868d7/6bdcf/Screen_Shot_2022-07-06_at_13.52.58.png 315w,\n/static/ff99d3872bc64caa7bbc2f92e2f868d7/f058b/Screen_Shot_2022-07-06_at_13.52.58.png 630w,\n/static/ff99d3872bc64caa7bbc2f92e2f868d7/40601/Screen_Shot_2022-07-06_at_13.52.58.png 945w,\n/static/ff99d3872bc64caa7bbc2f92e2f868d7/78612/Screen_Shot_2022-07-06_at_13.52.58.png 1260w,\n/static/ff99d3872bc64caa7bbc2f92e2f868d7/bcec6/Screen_Shot_2022-07-06_at_13.52.58.png 1834w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p class=\"figure-caption\">Identificador con ID = 1111111-1, y patientId = 5dedf…</p>\n<p>Para lograrlo, son dos pasos:</p>\n<h3>1) Agregar colección de identificadores</h3>\n<p>Al crear pacientes, ahora tenemos que también crear identificadores. Por ejemplo:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">const</span> patientRef <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token comment\">// ID auto generado</span>\n<span class=\"token keyword\">const</span> identifierRef <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'identifiers'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span> <span class=\"token comment\">// ID de RUT</span>\n\n<span class=\"token keyword\">await</span> identifierRef<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> patientId<span class=\"token operator\">:</span> patientRef<span class=\"token punctuation\">.</span>id <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">await</span> patientRef<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Aquí estamos creando ambos documentos. El problema es que esta no es una <a href=\"https://es.wikipedia.org/wiki/Operaci%C3%B3n_at%C3%B3mica#:~:text=Una%20operaci%C3%B3n%20at%C3%B3mica%20es%20una,la%20operaci%C3%B3n%20se%20haya%20completado.\">operación atómica</a>, es decir, si falla la creación de uno, el otro documento no se ve afectado.</p>\n<p>Para solucionar este problema, tenemos que usar <a href=\"https://firebase.google.com/docs/firestore/manage-data/transactions#batched-writes\">escrituras en lotes (Batch writes)</a>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">const</span> batch <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">batch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> patientRef <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> identifierRef <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'identifiers'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\nbatch<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>patientRef<span class=\"token punctuation\">,</span> newPatient<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nbatch<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>identifierRef<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> patientId<span class=\"token operator\">:</span> patientRef<span class=\"token punctuation\">.</span>id <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">await</span> batch<span class=\"token punctuation\">.</span><span class=\"token function\">commit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Ocurrió un error. Quizás el RUT ya estaba en uso :)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Con esto tenemos listo la primera parte. Ahora debemos hacer que esta operación falle si el RUT está en uso.</p>\n<h3>2) Agregar reglas de seguridad para evitar duplicados</h3>\n<p>Si ya existe un paciente con el RUT, la creación de paciente debe fallar. Como estamos usando una transacción, basta con la siguiente regla de seguridad:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\">match <span class=\"token operator\">/</span>identifiers<span class=\"token operator\">/</span><span class=\"token punctuation\">{</span>identifierId<span class=\"token punctuation\">}</span> <span class=\"token punctuation\">{</span>\n  allow create<span class=\"token operator\">:</span> <span class=\"token keyword\">if</span> <span class=\"token string\">'patientId'</span> <span class=\"token keyword\">in</span> request<span class=\"token punctuation\">.</span>resource<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Encapsulando la lógica anterior en una función llamada <code class=\"language-text\">createPatient</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">createPatient</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">patientData</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\t<span class=\"token keyword\">const</span> batch <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">batch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">const</span> patientRef <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token keyword\">const</span> identifierRef <span class=\"token operator\">=</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'identifiers'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\n\tbatch<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>patientRef<span class=\"token punctuation\">,</span> newPatient<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\tbatch<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>identifierRef<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> patientId<span class=\"token operator\">:</span> patientRef<span class=\"token punctuation\">.</span>id <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t\n\t<span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n\t  <span class=\"token keyword\">await</span> batch<span class=\"token punctuation\">.</span><span class=\"token function\">commit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\t<span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">{</span>\n\t  <span class=\"token comment\">// Ocurrió un error. Quizás el RUT ya estaba en uso :)</span>\n\t<span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Al intentar ejecutar el siguiente código, obtenemos el siguiente resultado:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">await</span> <span class=\"token function\">createPatient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> rut<span class=\"token operator\">:</span> <span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">,</span> name<span class=\"token operator\">:</span> <span class=\"token string\">'Chewy 1'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// ^funciona, y crea al paciente y al identificador (id = 11111111-1)</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">createPatient</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> rut<span class=\"token operator\">:</span> <span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">,</span> name<span class=\"token operator\">:</span> <span class=\"token string\">'Chewy 2'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token comment\">// ^falla, identificador id = 11111111-1 ya existe, la operación se considera</span>\n<span class=\"token comment\">// como un update, por lo tanto las reglas de seguridad la rechazan</span></code></pre></div>\n<p>Esto ocurre porque el segundo llamado está escribiendo sobre el identifier con ID igual a 11111111-1, como ya existe, estamos hablando de una operación <code class=\"language-text\">update</code> la cual no es permitida.</p>\n<p>Pero la regla no evita que agreguemos los pacientes directamente:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token comment\">// Las siguientes llamadas funcionan:</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> rut<span class=\"token operator\">:</span> <span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">,</span> name<span class=\"token operator\">:</span> <span class=\"token string\">'Chewy 1'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> rut<span class=\"token operator\">:</span> <span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">,</span> name<span class=\"token operator\">:</span> <span class=\"token string\">'Chewy 2'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Ni tampoco evita que agreguemos identificadores cuando los pacientes no existen:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">await</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'identifiers'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span><span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> patientId<span class=\"token operator\">:</span> <span class=\"token string\">'no existe'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Es por eso que necesitamos agregar las siguientes 2 reglas:</p>\n<p><strong>1) Cuando creo un identificador, verificar que el paciente existe:</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">patientExists</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">identifierId</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> identifier <span class=\"token operator\">=</span> <span class=\"token function\">getAfter</span><span class=\"token punctuation\">(</span><span class=\"token operator\">/</span>databases<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>database<span class=\"token punctuation\">)</span><span class=\"token operator\">/</span>documents<span class=\"token operator\">/</span>identifiers<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>identifierId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> patient <span class=\"token operator\">=</span> <span class=\"token function\">getAfter</span><span class=\"token punctuation\">(</span><span class=\"token operator\">/</span>databases<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>database<span class=\"token punctuation\">)</span><span class=\"token operator\">/</span>documents<span class=\"token operator\">/</span>patients<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>identifider<span class=\"token punctuation\">.</span>patientId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> identifierId <span class=\"token operator\">==</span> patient<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nmatch <span class=\"token operator\">/</span>identifiers<span class=\"token operator\">/</span><span class=\"token punctuation\">{</span>identifierId<span class=\"token punctuation\">}</span> <span class=\"token punctuation\">{</span>\n  allow create<span class=\"token operator\">:</span> <span class=\"token keyword\">if</span> <span class=\"token function\">patientExists</span><span class=\"token punctuation\">(</span>identifierId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>La función <a href=\"https://firebase.google.com/docs/reference/rules/rules.firestore#.getAfter\">getAfter</a> obtiene el documento asumiendo que la solicitud actual se realiza correctamente. Si el paciente no existe, la verificación fallará, ya que el <code class=\"language-text\">getAfter</code> del paciente fallaría.</p>\n<p><strong>2) Cuando creo un paciente, verificar que el identificador existe:</strong></p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">identifierExists</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">patientId</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">let</span> patient <span class=\"token operator\">=</span> <span class=\"token function\">getAfter</span><span class=\"token punctuation\">(</span><span class=\"token operator\">/</span>databases<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>database<span class=\"token punctuation\">)</span><span class=\"token operator\">/</span>documents<span class=\"token operator\">/</span>patients<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>patientId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> identifier <span class=\"token operator\">=</span> <span class=\"token function\">getAfter</span><span class=\"token punctuation\">(</span><span class=\"token operator\">/</span>databases<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>database<span class=\"token punctuation\">)</span><span class=\"token operator\">/</span>documents<span class=\"token operator\">/</span>identifiers<span class=\"token operator\">/</span><span class=\"token function\">$</span><span class=\"token punctuation\">(</span>patient<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> identifier<span class=\"token punctuation\">.</span>patientId <span class=\"token operator\">==</span> patientId<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nmatch <span class=\"token operator\">/</span>patients<span class=\"token operator\">/</span><span class=\"token punctuation\">{</span>patientId<span class=\"token punctuation\">}</span> <span class=\"token punctuation\">{</span>\n  allow create<span class=\"token operator\">:</span> <span class=\"token keyword\">if</span> <span class=\"token function\">identifierExists</span><span class=\"token punctuation\">(</span>patientId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Esto es lo mismo que la regla anterior, pero desde el punto de vista del paciente.</p>\n<p>Gracias a estas dos reglas, los casos anteriores funcionan como deberían:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token comment\">// Prueba 1: ambas llamadas fallan porque no existe identifier</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> rut<span class=\"token operator\">:</span> <span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">,</span> name<span class=\"token operator\">:</span> <span class=\"token string\">'Chewy 1'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> rut<span class=\"token operator\">:</span> <span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">,</span> name<span class=\"token operator\">:</span> <span class=\"token string\">'Chewy 2'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Prueba 2: falla porque no existe paciente</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'identifiers'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span><span class=\"token string\">'11111111-1'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> patientId<span class=\"token operator\">:</span> <span class=\"token string\">'no existe'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>La única forma de crear pacientes ahora es con una operación atómica, como la que tenemos en la función <code class=\"language-text\">createPatient</code>.</p>\n<h2>Conclusión</h2>\n<p>En este artículo vimos como implementar la funcionalidad de “campo único” en Firestore.</p>\n<p>Como ejemplo, nos pusimos en la situación donde queremos guardar pacientes con un campo único <a href=\"https://es.wikipedia.org/wiki/Rol_%C3%9Anico_Tributario\">“RUT”</a>, que es un identificador único que tienen los ciudadanos en Chile 🇨🇱. De todos modos, puedes usar las mismas técnicas para otros tipos de identificadores, tales como pasaporte, nombres de usuario o incluso correos.</p>\n<p>Las técnicas que vimos son 2:</p>\n<ol>\n<li>La fácil, que es utilizando tu campo único como ID del documento.</li>\n<li>La difícil, que es utilizando una colección auxiliar que funciona como un registro que guarda los valores únicos.</li>\n</ol>\n<p>Me gustaría destacar que las técnicas mostradas le falta una capa adicional de privacidad, ya que el RUT estaría visible en el administrador:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/ec8879020c01984433210dccaf2ad109/05fb0/Screen_Shot_2022-07-06_at_13.19.54.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 42.405063291139236%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAABDklEQVQoz5VSXU+EMBDk//8/ow9qTj2IvQNaoN1+d9xyQo74YG6SCaG7nZ1habq2hRDfkOMAZwkxBnjvd4YQYK3F21mCyKLr2rVXLzO0nrnuD/2NmmbIyUAtDgtFGBdZ9J4JsYq6m7hU3D8TlHaQfEfbcOhvKBSIKeIkLD4uBKE8cs5/WEpGSgk8D/2SMTA7mXCdE9fKzmZk++3XJ16en3B6f8X1ItAPA/q+3znwuxBifZIvkCbjPCZoV1BxG/grWCPVKJ4Z2UF1cYwcD2eZNQzHXIyHmjSMIdyjwQOoDiosL887CyXlmqAO2urNff7/WKNVOOfYGS9SKd60Xv+CXfARZ5tg/UREtApvZ1vPD2NecPagXeHtAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Screen Shot 2022-07-06 at 13.19.54.png\"\n        title=\"Screen Shot 2022-07-06 at 13.19.54.png\"\n        src=\"/static/ec8879020c01984433210dccaf2ad109/f058b/Screen_Shot_2022-07-06_at_13.19.54.png\"\n        srcset=\"/static/ec8879020c01984433210dccaf2ad109/c26ae/Screen_Shot_2022-07-06_at_13.19.54.png 158w,\n/static/ec8879020c01984433210dccaf2ad109/6bdcf/Screen_Shot_2022-07-06_at_13.19.54.png 315w,\n/static/ec8879020c01984433210dccaf2ad109/f058b/Screen_Shot_2022-07-06_at_13.19.54.png 630w,\n/static/ec8879020c01984433210dccaf2ad109/40601/Screen_Shot_2022-07-06_at_13.19.54.png 945w,\n/static/ec8879020c01984433210dccaf2ad109/05fb0/Screen_Shot_2022-07-06_at_13.19.54.png 1138w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Además, ¿qué pasa si el campo único tiene caracteres que a Firebase no le gusta en sus IDs?</p>\n<p>Y solo vimos un único identificador, ¿cómo podemos hacer que existan otros tipos de identificadores? Por ejemplo, permitir que pacientes tengan RUT o Pasaporte.</p>\n<p>A continuación te dejo contenido extra de cómo abordar estos requerimientos.</p>\n<h2>Extra: Cómo esconder el identificador</h2>\n<p>Si no quieres que tu campo único esté visible desde Firebase:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/ec8879020c01984433210dccaf2ad109/05fb0/Screen_Shot_2022-07-06_at_13.19.54.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 42.405063291139236%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAABDklEQVQoz5VSXU+EMBDk//8/ow9qTj2IvQNaoN1+d9xyQo74YG6SCaG7nZ1habq2hRDfkOMAZwkxBnjvd4YQYK3F21mCyKLr2rVXLzO0nrnuD/2NmmbIyUAtDgtFGBdZ9J4JsYq6m7hU3D8TlHaQfEfbcOhvKBSIKeIkLD4uBKE8cs5/WEpGSgk8D/2SMTA7mXCdE9fKzmZk++3XJ16en3B6f8X1ItAPA/q+3znwuxBifZIvkCbjPCZoV1BxG/grWCPVKJ4Z2UF1cYwcD2eZNQzHXIyHmjSMIdyjwQOoDiosL887CyXlmqAO2urNff7/WKNVOOfYGS9SKd60Xv+CXfARZ5tg/UREtApvZ1vPD2NecPagXeHtAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Screen Shot 2022-07-06 at 13.19.54.png\"\n        title=\"Screen Shot 2022-07-06 at 13.19.54.png\"\n        src=\"/static/ec8879020c01984433210dccaf2ad109/f058b/Screen_Shot_2022-07-06_at_13.19.54.png\"\n        srcset=\"/static/ec8879020c01984433210dccaf2ad109/c26ae/Screen_Shot_2022-07-06_at_13.19.54.png 158w,\n/static/ec8879020c01984433210dccaf2ad109/6bdcf/Screen_Shot_2022-07-06_at_13.19.54.png 315w,\n/static/ec8879020c01984433210dccaf2ad109/f058b/Screen_Shot_2022-07-06_at_13.19.54.png 630w,\n/static/ec8879020c01984433210dccaf2ad109/40601/Screen_Shot_2022-07-06_at_13.19.54.png 945w,\n/static/ec8879020c01984433210dccaf2ad109/05fb0/Screen_Shot_2022-07-06_at_13.19.54.png 1138w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Puedes “ofuscar” el identificador, de manera que en vez de guardar el RUT, guardes su valor encriptado.</p>\n<p>Para esto, tienes que usar alguna función que <a href=\"https://firebase.google.com/docs/reference/rules/rules.hashing\">esté disponible en Cloud Firestore Rules</a>, por ejemplo, <code class=\"language-text\">md5</code> o <code class=\"language-text\">sha256</code>.</p>\n<p>Usando <code class=\"language-text\">sha256</code>, el ID del documento ahora será el RUT encriptado:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">const</span> patientId <span class=\"token operator\">=</span> <span class=\"token function\">sha256</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span>\n<span class=\"token function\">firestore</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">collection</span><span class=\"token punctuation\">(</span><span class=\"token string\">'patients'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">doc</span><span class=\"token punctuation\">(</span>patientId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">)</span></code></pre></div>\n<p>Y tendrías que actualizar las reglas de seguridad para verificar que el RUT del paciente sea igual al RUT encriptado:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"language-jsx\"><code class=\"language-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">verifyPatientId</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">patientId<span class=\"token punctuation\">,</span> patientData</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> patientId <span class=\"token operator\">==</span> hashing<span class=\"token punctuation\">.</span><span class=\"token function\">sha256</span><span class=\"token punctuation\">(</span>patientData<span class=\"token punctuation\">.</span>rut<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toHexString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">lower</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nmatch <span class=\"token operator\">/</span>patients<span class=\"token operator\">/</span><span class=\"token punctuation\">{</span>patientId<span class=\"token punctuation\">}</span> <span class=\"token punctuation\">{</span>\n  allow create<span class=\"token operator\">:</span> <span class=\"token keyword\">if</span> <span class=\"token function\">verifyPatientId</span><span class=\"token punctuation\">(</span>patientId<span class=\"token punctuation\">,</span> request<span class=\"token punctuation\">.</span>resource<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  allow update<span class=\"token operator\">:</span> <span class=\"token keyword\">if</span> <span class=\"token function\">verifyPatientId</span><span class=\"token punctuation\">(</span>patientId<span class=\"token punctuation\">,</span> request<span class=\"token punctuation\">.</span>resource<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Así, el ID en vez de ser <code class=\"language-text\">11111111-1</code>, queda en <code class=\"language-text\">5dedf71e6903bbb3c0b08ab5d94db62a4a5dea268bf2ef8d591089345989f82f</code></p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 630px; \"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/f61f565e0fb8570a9a448c4f6f6668d8/c5bb3/Screen_Shot_2022-07-06_at_13.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 73.41772151898735%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsSAAALEgHS3X78AAABp0lEQVQ4y41Ta2+CQBDk//8p4yvqx5Y0hk+2iPJ+qIAciFNm7VlL1XjJuDt37u5wu2csl0vkeY5st8OuQ1EUqOsaSimx96DPqqpCEATXuOPxCGM8Hsvml21j7TiIkwRK/qwk8BmYMAxDZFmGw+Eg3ADXueXPD9qONp1p0DTNQ5UEz9u2xel0El8UfoYN7KjBu61grhUst8aHU+PNrlFUl0Ln8y/663afSY2qPkOdgKIGyg55dfELddF7L0Hf/5OQTp4fsN2sEQY+dlkiNvBd+L7XwZd72m63SNP0j6q+8mtCdsiTwAhJkiKKIkkSx7E0TPP9fv9P1cOEm81Gggn6ruvC6bpOS1Ahz/pJ7iZkd6gm6UaGn0VLrvc053i8rJDVb9XY3VzyU7nved6Vv5SQA6nVEQykIs0Jcn2Hj3DT5VxU6DukSjaBdrVaiWLeK4s+WxxwoyxLqUzwjhjEt0lVmtOS6zdLUARBnzlo+RwNKrIsC3zT8/kcpmmKnUwmguFwKJzn9Gmn06mcDQYDLBYLzGYzjEYjKWzoavqBk1OJVt33b3l/n734Bpjuff45jdFQAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Screen Shot 2022-07-06 at 13.png\"\n        title=\"Screen Shot 2022-07-06 at 13.png\"\n        src=\"/static/f61f565e0fb8570a9a448c4f6f6668d8/f058b/Screen_Shot_2022-07-06_at_13.png\"\n        srcset=\"/static/f61f565e0fb8570a9a448c4f6f6668d8/c26ae/Screen_Shot_2022-07-06_at_13.png 158w,\n/static/f61f565e0fb8570a9a448c4f6f6668d8/6bdcf/Screen_Shot_2022-07-06_at_13.png 315w,\n/static/f61f565e0fb8570a9a448c4f6f6668d8/f058b/Screen_Shot_2022-07-06_at_13.png 630w,\n/static/f61f565e0fb8570a9a448c4f6f6668d8/c5bb3/Screen_Shot_2022-07-06_at_13.png 680w\"\n        sizes=\"(max-width: 630px) 100vw, 630px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>El código de la segunda técnica bajo ofuscación te lo dejo como ejercicio 😆</p>","fields":{"tags":[{"name":"Tecnología","slug":"tecnologia"}]},"frontmatter":{"title":"Cómo implementar un campo único en Firestore","date":"08 de  julio, 2022","description":"Imagina que tienes que guardar un campo de RUT de pacientes en Firestore y que además tienes que preocuparte de no duplicarlos. ¿Cómo lo haces?","author":{"slug":"nico","avatar":{"childImageSharp":{"fixed":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAEqUlEQVQ4y22T2XMUVRSH58kHtRDIOpnp7pnuniXbJJMdshEyIQnZYFgCRCKEJJCwC0mUFMpigEBYEtawhCAJBgEt1iqg1BIpKUuLguJBLV98sKzywb/h83SHzdKHU32r77nf/f3OPceRYMzCini9VL5lOP2VuFLqUNKiqBlLUcLNqFkr0SRUWSuhxbK3QHIacAaqSDBn22cnz8/C8RImG0nBGtySrGYuQ8teiTeniUC4iuRwBWaoEm84ije/E092i52jpC/ElVxLoq/8FfAlTDaU9EV4spaj5XUQyKkjMiOTmSGDUMCL36tieD2YGRGBtkuskdz3UEONorZeoJEXCstE2dznsGb0gnUYuUuIFGbRUJhCrplId1MthekBprz9DlPeegO3kYlR3PVc7cpJqKVUhDmsmrmlXprUR89fjV7cQ1p+PeVhnfLsIHvWr+Dvn+7y682z9K9vJqC5mD49BqNoI0ZJj5zpsJVa9pMC1ThcyXV28b25begzN2KW78aXs5gsbwxb3m3g6/Fh/vjhPs9ujzO27wM6Fs8hLjYWvbRHcnehF72PN281WmYT7tQGHJY66wbbqtzoqzyAUtTNqmiE7y4c4kTPOp5eO8mnOzbQ29JEX+ciQkGdpMIu/FUHMUo/FCEbbOuWSofVBp6cVvTCzZhlH+GbewSlbDe961r5/avLPL1+kd9ujPDZzg08GBng3qmdVBZlo5Rux1dzFHP2DrG/RRy2i9MlOGy7Itko3opPLHirBglFhzm9byd/PrrDXw9v8WB0kMObWngydoibxz5maSSbUN1B9JoTmJFPbGdeqaUWbhKg9JPVAkZJt2z2YcwdIjD/Agf6h3l8a4SHE2d4NHGRKwf3MLJ7CwPdzTRE2whGL2DUHMes2Dtpu2CtAJf/F2jWDKHXj5Kx9DIT54d5cuM0T66Mc3toP6N9a9nUuYLUxs8x549J7rH/Ab5m2Xpho/oI/nln0edfob1riHuXDvP07jVujwzS3VZLdbSF5MYv8TWcs93Yrl63bD2K97VHMSr346s/hdpwmc6uo5wb2Mq2zR00L6yhqthPbW09/uglzPqzGFUDrx4lr91uP7tttBdtU9qLOadfXvoQrpJe2lat4fGd0/Rva6dlUTndrdUsq5uJK7dF7A5K7gGMWdv/3TZ2Y0tT6nmtGAVtApcRTC1FDeYRidSI3XF+vHWeqyd3cfV4Lw3VFUyNV1ED+eKsEWOGDER+mz1p7tR51uhVoKXORgsWyIyGUMx0NH8WeuoMFH8eo4N7eXZ/gu+/OMPYUB/eQJgkPR3Vl4HLE8Stp0leLkqwREYvIkBDmtQUkC9TvhK+bNxmGE8wB5cklkdq+eWb6/z87R2qqqPEa2kCScepJZOgBCSC9jpR9RPrCuBIVFNw+7JEYQ5aIIckb7oNtEIVpdOcfjpXtbFkQSNvTnWR5EnB6Uklzu0nQRWQliKwZOLdAaYnaDhinSZOgShyWBGw6s+24YovbK9VuSTG5Ze6eXCJMivHLXsuI0OshwRowXwC8zAtXoAxiTpxcsACTKp6DhT7L1RbSj3B3EmY/LfCJfV2etJs27FJBlPj3EyLU/gHBhzbgqfkxlYAAAAASUVORK5CYII=","width":70,"height":70,"src":"/static/c454b7eddf2624b2e434eb2b68050446/31406/nico.png","srcSet":"/static/c454b7eddf2624b2e434eb2b68050446/31406/nico.png 1x,\n/static/c454b7eddf2624b2e434eb2b68050446/1edbf/nico.png 1.5x,\n/static/c454b7eddf2624b2e434eb2b68050446/b3779/nico.png 2x"}}},"bio":"Ingeniero Civil en Computación PUC.","github":"muZk","linkedin":"codewithnico","name":"Nicolás Gómez","twitter":"codewithnico"},"image":{"childImageSharp":{"resize":{"src":"/static/761134b417e50e230b0a57daed1def97/47498/preview.jpg","height":624,"width":1200}}}}},"previous":{"fields":{"slug":"/como-fue-trabajar-2-semanas-en-reino-unido/"},"frontmatter":{"title":"Cómo fue trabajar 2 semanas desde Reino Unido"}},"next":{"fields":{"slug":"/que-es-hl7-fhir/"},"frontmatter":{"title":"¿Qué es HL7 FHIR?"}}},"pageContext":{"id":"980332af-7603-535a-8814-7a6f4727c1a0","previousPostId":"e54242e8-b126-5735-a594-165f9ae03892","nextPostId":"078fce0a-8d37-503b-b55e-875f0130c3d9"}},"staticQueryHashes":["3832538981"]}