sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB $indexOfBytes

En MongoDB, el $indexOfBytes El operador de canalización de agregación busca en una cadena una aparición de una subcadena y devuelve el índice de bytes UTF-8 de la primera aparición.

El índice de bytes UTF se basa en cero (es decir, comienza en 0 ).

Sintaxis

La sintaxis es así:

{ $indexOfBytes: [ <string expression>, <substring expression>, <start>, <end> ] }

donde:

  • <string expression> es la cadena a buscar.
  • <substring expression> es la subcadena que desea encontrar en la cadena.
  • <start> es un argumento opcional que especifica una posición de índice inicial para la búsqueda. Puede ser cualquier expresión válida que se resuelva en un número entero no negativo.
  • <end> es un argumento opcional que especifica una posición de índice final para la búsqueda. Puede ser cualquier expresión válida que se resuelva en un número entero no negativo.

Si no se encuentra el valor especificado, $indexOfBytes devuelve -1 .

Si hay varias instancias del valor especificado, solo se devuelve la primera.

Ejemplo

Supongamos que tenemos una colección llamada test con los siguientes documentos:

{ "_id" : 1, "data" : "c 2021" }
{ "_id" : 2, "data" : "© 2021" }
{ "_id" : 3, "data" : "ไม้เมือง" }

Aquí hay un ejemplo de cómo aplicar $indexOfBytes a esos documentos:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2, 3 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "2021" ] }
          }
     }
   ]
)

Resultado:

{ "data" : "c 2021", "result" : 2 }
{ "data" : "© 2021", "result" : 3 }
{ "data" : "ไม้เมือง", "result" : -1 }

Podemos ver que los dos primeros documentos produjeron resultados diferentes, aunque la subcadena parece estar en la misma posición para cada documento. En el primer documento, la subcadena se encontró en la posición del índice de bytes 2 , mientras que el segundo documento lo tenía en 3 .

La razón de esto es que el símbolo de copyright (© ) en el segundo documento ocupa 2 bytes. El c El carácter (en el primer documento) solo usa 1 byte. El carácter de espacio también usa 1 byte.

El resultado de $indexOfBytes está basado en cero (el índice comienza en 0 ), por lo que terminamos con un resultado de 2 y 3 respectivamente.

Con respecto al tercer documento, la subcadena no se encontró en absoluto, por lo que el resultado es -1 .

Aquí hay otro ejemplo, excepto que esta vez buscamos un carácter tailandés:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1, 2, 3 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "เ" ] }
          }
     }
   ]
)

Resultado:

{ "data" : "c 2021", "result" : -1 }
{ "data" : "© 2021", "result" : -1 }
{ "data" : "ไม้เมือง", "result" : 9 }

En este caso, buscamos un carácter que aparece en la tercera posición en el tercer documento, y su índice de bytes UTF-8 regresa como 9 .

Esto se debe a que, en este caso, cada carácter utiliza 3 bytes. Pero el segundo carácter tiene una marca diacrítica, que también tiene 3 bytes. Por lo tanto, los dos primeros caracteres (incluido el diacrítico) utilizan 9 bytes. Dada la indexación basada en cero, sus índices de bytes UTF-8 van desde 0 a 8 . Esto significa que el tercer carácter comienza en la posición 9 .

Ver MongoDB $strLenBytes para un ejemplo que devuelve el número de bytes para cada carácter en esta cadena en particular.

Especifique una posición inicial

Puede proporcionar un tercer argumento para especificar una posición de índice inicial para la búsqueda.

Supongamos que tenemos el siguiente documento:

{ "_id" : 4, "data" : "ABC XYZ ABC" }

Aquí hay un ejemplo de cómo aplicar $indexOfBytes con una posición inicial:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 4 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "ABC", 1 ] }
          }
     }
   ]
)

Resultado:

{ "data" : "ABC XYZ ABC", "result" : 8 }

En este caso, se devolvió la segunda instancia de la subcadena. Esto se debe a que comenzamos la búsqueda en la posición 1 , y la primera instancia de la subcadena comienza en la posición 0 (antes de la posición inicial de la búsqueda).

Si la posición inicial es un número mayor que la longitud en bytes de la cadena o mayor que la posición final, $indexOfBytes devuelve -1 .

Si es un número negativo, $indexOfBytes devuelve un error.

Especifique una posición final

También puede proporcionar un cuarto argumento para especificar la posición final del índice para la búsqueda.

Si proporciona este argumento, también debe proporcionar una posición inicial. Si no lo hace, este argumento se interpretará como el punto de partida.

Ejemplo:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 4 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "XYZ", 0, 5 ] }
          }
     }
   ]
)

Resultado:

{ "data" : "ABC XYZ ABC", "result" : -1 }

El resultado es -1 lo que significa que no se encontró la subcadena. Eso es porque comenzamos nuestra búsqueda en la posición 0 y lo terminó en la posición 5 , por lo tanto, no captura la subcadena.

Esto es lo que sucede si incrementamos la posición final del índice:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 4 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "XYZ", 0, 7 ] }
          }
     }
   ]
)

Resultado:

{ "data" : "ABC XYZ ABC", "result" : 4 }

Esta vez se incluyó el valor y se devolvió su posición de índice.

Si la posición final es un número menor que la posición inicial, $indexOfBytes devuelve -1 .

Si es un número negativo, $indexOfBytes devuelve un error.

Campos faltantes

Si el campo no está en el documento, $indexOfBytes devuelve null .

Supongamos que tenemos el siguiente documento:

{ "_id" : 5 }

Esto es lo que sucede cuando aplicamos $indexOfBytes :

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 5 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "XYZ" ] }
          }
     }
   ]
)

Resultado:

{ "result" : null }

Valores nulos

Si el primer argumento es null , $indexOfBytes devuelve null .

Supongamos que tenemos el siguiente documento:

{ "_id" : 6, "data" : null }

Esto es lo que sucede cuando aplicamos $indexOfBytes :

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 6 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "XYZ" ] }
          }
     }
   ]
)

Resultado:

{ "data" : null, "result" : null }

Sin embargo, cuando el segundo argumento (es decir, la subcadena) es null , se devuelve un error:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", null ] }
          }
     }
   ]
)

Resultado:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$indexOfBytes requires a string as the second argument, found: null",
	"code" : 40092,
	"codeName" : "Location40092"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Tipo de datos incorrecto

Si el primer argumento es del tipo de datos incorrecto (es decir, no se resuelve en una cadena), $indexOfBytes devuelve un error.

Supongamos que tenemos el siguiente documento:

{ "_id" : 7, "data" : 123 }

Esto es lo que sucede cuando aplicamos $indexOfBytes a ese documento:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 7 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result: { $indexOfBytes: [ "$data", "XYZ" ] }
          }
     }
   ]
)

Resultado:

uncaught exception: Error: command failed: {
	"ok" : 0,
	"errmsg" : "$indexOfBytes requires a string as the first argument, found: double",
	"code" : 40091,
	"codeName" : "Location40091"
} : aggregate failed :
[email protected]/mongo/shell/utils.js:25:13
[email protected]/mongo/shell/assert.js:18:14
[email protected]/mongo/shell/assert.js:639:17
[email protected]/mongo/shell/assert.js:729:16
[email protected]/mongo/shell/db.js:266:5
[email protected]/mongo/shell/collection.js:1058:12
@(shell):1:1

Como indica el mensaje de error, $indexOfBytes requires a string as the first argument .