Andres Roberto Coello Goyes
3 dias para llegar aqui.. :(
Luis Jeanpier Monserrate
Igual me paso a mi jajaja
silvana murgo
la configuración de la bd estuvo brava! :P
Unions permite agrupar varios custom types sin importar si tienen algo en común, su sintaxis es la siguiente:
union SearchResult = CustomType1 | CustomType2 | CustomType3
Al momento de realizar una query que retorna una union podemos identificar el tipo de dato solicitando el campo __typename.
Andres Roberto Coello Goyes
3 dias para llegar aqui.. :(
Luis Jeanpier Monserrate
Igual me paso a mi jajaja
silvana murgo
la configuración de la bd estuvo brava! :P
Alberto D. Sosa
Query para crear indices:
db.<collection>.createIndex({"$**": "text"})
Juan Jose Vega
Alguien sabe cómo hacer eso con mongo compass?
Juan Jose Vega
Siiii, muchas gracias!
Para los que están usando Mongo Compass y no pueden crear los índices: En las últimas versiones de Compass, hasta abajo en una franja aparece una sección ">_MongoSH". incluso a mí al día de hoy me aparece en beta. (Si no les aparece actualicen a la última versión de Compass. Yo tengo la versión 1.22.1) .
Den clic en ella y accederán al Shell de Mongo. Ahí pueden correr los siguientes comandos. .
show dbs // Lista todas sus bases de datos. use <nombre de su base de datos> // use graphql-api_db por ejemplo. show collections // Lista las colecciones en esa base de datos. db.courses.createIndex({"$**": "text"}) // Pueden cambiar el "courses" en caso de que sus colecciones tengan diferente nombre. db.students.createIndex({"$**": "text"}) // Lo mismo para "students" en caso de nombre distinto.
Eso debería dejar listos los índices para poder trabajar con ellos y correr el query.
Les recomiendo esta clase si quieren que les quede más claro. https://platzi.com/clases/1533-mongodb/18493-consultas-mas-rapidas-con-indices/
Unions
Unions permite hacer lo mismo que interfaces pero de una manera más extrema.
Agregamos una union a nuestro schema:
union GlobalSearch = Course | Student | Monitor type Query { "Devuelve todos los cursos" getCourses: [Course] "Devuelve un curso" getCourse(id: ID!): Course "Devuelve todos los estudiantes" getPeople: [Person] "Devuelve un estudiante" getPerson(id: ID!): Person "Ejecuta una búsqueda global" searchItems(keyword: String!): [GlobalSearch] }
Agregamos en types.js:
GlobalSearch: { __resolveType: (item, context, info) => { if (item.title){ return 'Course' } if (item.phone) { return 'Monitor' } return 'Student' } }
Agregamos en queries.js:
searchItems: async (root, { keyword }) => { let db let items let courses let people try { db = await connectDb() courses = await db.collection('courses').find({ $text: { $search: keyword } }).toArray() people = await db.collection('students').find({ $text: { $search: keyword } }).toArray() items = [...courses, ...people] } catch (error) { errorHandler(error); } return items }
Antes de continuar, debemos crear índices en MongoDB:
db.courses.createIndex({ "$**": "text" }) & db.students.createIndex({ "$**": "text" })
Y ahora podemos hacer por ejemplo esta querie:
{ searchItems(keyword: "programming") { __typename ... on Course { title description topic } ... on Monitor { name phone } ... on Student { name email } } }
Y como el keyword que (al menos yo escogí) es 'programming', regresa un resultado:
{ "data": { "searchItems": [ { "__typename": "Course", "title": "New cool title", "description": "My description", "topic": "Programming" }, { "__typename": "Course", "title": "My title 3", "description": "My description 3", "topic": "Programming" } ] } }
Pablo Estornut
Al hacer el query si busco "Titulo" obtengo resultados, pero no si busco "T", al parecer el indice "text" solo busca palabras iguales, pero ¿Cómo se pueden buscar que contenga la cualquier cadena?
Jorge Alberto Bonelli Nasta
Hola, pudiste solucionar esa duda, yo tambien estoy batallando con eso, al parecer mongo no permite hacer consultas de ese tipo con indices, creo que toca haria hacer otro tipo de consulta, alguna sugerencia?
Darwin Salinas
Qué tan óptimo es realizar índices de este tipo en mongo? lo pregunto porque cuando se hace la búsqueda, esta revisa en cada uno de los campos
Javier Fuentes Mora
ProfesorSi quieren ampliar un poco mas sobre el tema https://platzi.com/clases/1533-mongodb/18493-consultas-mas-rapidas-con-indices/
Armando Rivera
No entiendo muy bien el úso de los índices, alguien me puede explicar cómo funcionan?
Reinaldo Mendoza
Gracias por la explicacion
Julian Franco
Para los que están utilizando MongoDB Atlas, hay una forma nueva de crear y utilizar search indexes. Esta forma utliliza aggregate en vez de find. La documentación esta en: https://docs.atlas.mongodb.com/reference/atlas-search/path-construction#wildcard-field-search
{ "mappings": { "dynamic": true } }
const courses = await db .collection('courses') .aggregate([ { $search: { index: 'default', text: { query: keyword, path: { wildcard: '*' }, }, }, }, ]) .toArray();
Asi logramos crear el query de esta lección usando MongoDB Atlas sin conectarnos desde el shell y creando el index del curso.
Francisco Garcia [C6]
Excelente.
{ searchItems(keyword: "ejemplo"){ __typename ... on Course{ title description } ... on Monitor { name phone } ... on Student { name email } } }
{ "data": { "searchItems": [ { "__typename": "Course", "title": "Curso de ejemplo numero 1", "description": "una descripcion 1" } ] } }
Guerin Steven Colocho Chacón
¿Se puede hacer un schema por cada entidad? es que tener todas las entidades en un solo esquema se me hace que es un poco desordenado
Luis Lira
Sí, puedes crear schemas para cada entidad. Personalmente yo no lo escribo en archivo .js mis archivos de GraphQL, yo lo ahgo con la extensión de .graphql y luego hago merge de los schemas usando graphql-tools :D y lo mismo para los resolvers
Así el código queda modularizado y más escalable a mi parecer
José Andrés Nava Campos
Javier Fuentes Mora
Profesoryo tengo este mismo error lo lograste resolver?
Javier Fuentes Mora
ProfesorYa lo logre resolver estaba usando , solo mongo Atlas pero no encontre como crear un indice de type text , tuve que instalar Robo 3 T y crearlo mediante el comando que usa el profesor
Jorge Alberto Bonelli Nasta
Alguno sabe cómo solucionar el tema de consultas que no sea obligatio el match de la palabra completa, me explico, si quiero buscar "carro". a medida que escriba "ca" pueda ir consultando y me traiga esa info.
Gracias.
César David Ramírez Dimaté
Cristian Caraballo
Alguien me puede ayudar o indicar como hacer la indexacion con mongodb compass ?
Erasmo Hernández
ProfesorEn la parte inferior de Compass tienes una pestaña con la Shell de compass, la abres y puedes ejecutar el mismo comando que hizo el profesor en la clase.
Juan ibañez
De esta manera podriamos buscar de manera mas dinamica, mediante busqueda regex, sin embargo hasta donde he encontrado si quiero que busque en todos los campos con una sola query find, no lo permite, debemos ingresar cada field
const courses = await db .collection("courses") .find({ title: { $regex: `${keyword}.*`, }, })
Juan ibañez
César David Ramírez Dimaté
Nicolas David Pastran Zamora
No me quedo claro una cosa en la creación de indices. El indice se crea para todos los campos tipo String de la colección o para un solo campo ?
César David Ramírez Dimaté
Para todos los campos. Si buscas un texto en el campo de title, topic, description, name, etc traerá el resultado si coincide en la búsqueda (por eso añadió números al name de Student y Monitor, para verificar esto).
Usuario anónimo
User:)
Francisco Garcia [C6]
Para los que usamos Ubuntu, los index los trate de crear por Atlas, pero no funcionaron en un principio. Los podemos crear por la linea de comando de mongo shell, con la misma instrucción tal como los explica el profe.
jorge llanque
Excelente explicacion
Hola, alguien sabe por qué me regresa este error?
{ MongoError: text index required for $text query at MessageStream.messageHandler (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/connection.js:261:20) at emitOne (events.js:116:13) at MessageStream.emit (events.js:211:7) at processIncomingData (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:144:12) at MessageStream._write (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:42:5) at doWrite (_stream_writable.js:396:12) at writeOrBuffer (_stream_writable.js:382:5) at MessageStream.Writable.write (_stream_writable.js:290:11) at TLSSocket.ondata (_stream_readable.js:639:20) at emitOne (events.js:116:13) operationTime: Timestamp { _bsontype: 'Timestamp', low_: 9, high_: 1582842781 }, ok: 0, errmsg: 'text index required for $text query', code: 27, codeName: 'IndexNotFound', '$clusterTime': { clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 9, high_: 1582842781 }, signature: { hash: [Object], keyId: [Object] } }, name: 'MongoError', [Symbol(mongoErrorContextSymbol)]: {} } { MongoError: text index required for $text query at MessageStream.messageHandler (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/connection.js:261:20) at emitOne (events.js:116:13) at MessageStream.emit (events.js:211:7) at processIncomingData (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:144:12) at MessageStream._write (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:42: Programacion/graphQL/platzi-dir ▶ node index.js Server is listening at http://localhost:3000/api { MongoError: text index required for $text query at MessageStream.messageHandler (/Users/andresnava/Documents/Progr amacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/connection.js :261:20) at emitOne (events.js:116:13) at MessageStream.emit (events.js:211:7) at processIncomingData (/Users/andresnava/Documents/Programacion/g raphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:144: 12) at MessageStream._write (/Users/andresnava/Documents/Programacion/ graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:42: 5) at doWrite (_stream_writable.js:396:12) at writeOrBuffer (_stream_writable.js:382:5) at MessageStream.Writable.write (_stream_writable.js:290:11) at TLSSocket.ondata (_stream_readable.js:639:20) at emitOne (events.js:116:13) operationTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1 582842800 }, ok: 0, errmsg: 'text index required for $text query', code: 27, codeName: 'IndexNotFound', '$clusterTime': { clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1582842800 }, signature: { hash: [Object], keyId: [Object] } }, name: 'MongoError', [Symbol(mongoErrorContextSymbol)]: {} } { MongoError: text index required for $text query at MessageStream.messageHandler (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/connection.js:261:20) at emitOne (events.js:116:13) at MessageStream.emit (events.js:211:7) at processIncomingData (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:144:12) at MessageStream._write (/Users/andresnava/Documents/Programacion/graphQL/platzi-dir/node_modules/mongodb/lib/cmap/message_stream.js:42:5) at doWrite (_stream_writable.js:396:12) at writeOrBuffer (_stream_writable.js:382:5) at MessageStream.Writable.write (_stream_writable.js:290:11) at TLSSocket.ondata (_stream_readable.js:639:20) at emitOne (events.js:116:13) operationTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1582842800 }, ok: 0, errmsg: 'text index required for $text query', code: 27, codeName: 'IndexNotFound', '$clusterTime': { clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 2, high_: 1582842800 }, signature: { hash: [Object], keyId: [Object] } }, name: 'MongoError', [Symbol(mongoErrorContextSymbol)]: {} }
searchItems: async (root, { keyword }) => { let db; let items; let courses; let people; try { db = await connectDb(); courses = await db.collection('courses').find( { $text: { $search: keyword} } ).toArray(); people = await db.collection('students').find( { $text: { $search: keyword} } ).toArray(); items = [...courses, ...people]; } catch (error) { errorHandler(error); } return items; }
Acabo de hacer la tarea. Realmente el artículo de referencia es este (ya que es un tema propio de mongodb, no de graphql), donde:
db.<nombre_coleccion>.find({"<nombre_campo>": /<valor_campo>/}) // LIKE '%<valor_campo>%'. db.<nombre_coleccion>.find({"<nombre_campo>": /^<valor_campo>/}) // LIKE '<valor_campo>%'. db.<nombre_coleccion>.find({"<nombre_campo>": /<valor_campo>$/}) // LIKE '%<valor_campo>'.
Recuerda que todo lo que desees hacer debes construirlo en el resolver. Pero qué pasa con la búsqueda por índices, se debe escribir la palabra completa para que funcione, no una parte. Si escribes "ejemplo" te trae resultados, pero si trae "ejem" no traerá nada. Esto se debe a que las expresiones regulares (++$regex++) sólo se pueden hacer por medio de campos y no de índices.
Para que funcione con una parte de la palabra en la búsqueda, tendrías que en el resolver mapear cada campo, por ejemplo:
courses = await db.collection('courses').find({ $or: [ { title: { $regex: keyword }}, { description: { $regex: keyword }}, { topic: { $regex: keyword }} ]}).toArray()
En este caso solo me gustaria que buscara basado en description o title, tambien vendria bien crear otro field, que contenga toda la info base de busqueda y aplicamos solo un regex sobre este field
const courses = await db .collection("courses") .find({ $or: [ { title: { $regex: `${keyword}.*`, }, }, { description: { $regex: `${keyword}.*`, }, }, ], }) .toArray();
Estaba revisando lo que mencionas y sólo escribiendo así funciona, sin necesidad de poner keyword entre corchetes...
courses = await db.collection('courses').find({ title: { $regex: keyword }}).toArray()
No tiene sentido crear un field que contenga toda la info de la base de búsqueda (por eso se crearon los índices). Pero, si se puede construir otro query en GraphQL para que lo haga sólo para campos específicos, ya el resto es cómo construyas la consulta de MongoDB en el código.
// Busca en todos los campos. courses = await db.collection('courses').find({ $text: { $search: keyword }}).toArray() // Buscar sólo en el campo 'title'. courses = await db.collection('courses').find({ title: { $regex: keyword }}).toArray() // Busca sólo en el campo 'title' o 'description'. courses = await db.collection('courses').find({ $or: [{ title: { $regex: keyword }}, { description: { $regex: keyword }}] }).toArray()