sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB $substrBytes

I MongoDB, $substrBytes aggregeringspipeline-operatorn returnerar delsträngen till en sträng, baserat på de angivna UTF-8-kodade byteindexen.

Syntax

Syntaxen ser ut så här:

{ $substrBytes: [ <string expression>, <byte index>, <byte count> ] }

Var:

  • är strängen. Det kan vara vilket giltigt uttryck som helst så länge det löser sig till en sträng.
  • är var du ska börja delsträngen. Det kan vara vilket giltigt uttryck som helst så länge det löser sig till ett icke-negativt heltal eller tal som kan representeras som ett heltal.
  • är hur många byte delsträngen ska fortsätta för. Det kan vara vilket giltigt uttryck som helst så länge det löser sig till ett icke-negativt heltal eller tal som kan representeras som ett heltal.

Exempel

Föreställ dig att vi har en samling som heter tester med följande dokument:

{ "_id" : 1, "data" : "Red Firetruck" }

Vi kan använda $substrBytes så här:

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

Resultat:

{ "data" : "Red Firetruck", "result" : "Red" }

Indexet börjar på noll, så vår delsträng började i början av strängen och fortsatte i tre byte.

I det här fallet använder vi engelska tecken och varje tecken är en byte. Detta gör det enkelt för oss att räkna hur många byte som ska användas.

Låt oss köra ett annat exempel:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 1 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            result_1: { $substrBytes: [ "$data", 4, 4 ] },
            result_2: { $substrBytes: [ "$data", 8, 5 ] },
            result_3: { $substrBytes: [ "$data", 8, 20 ] }
          }
     }
   ]
).pretty()

Resultat:

{
	"data" : "Red Firetruck",
	"result_1" : "Fire",
	"result_2" : "truck",
	"result_3" : "truck"
}

Observera att i vårt tredje resultat angav vi fler byte än vad som var tillgängliga, men det returnerade helt enkelt alla tecken till slutet av strängen.

Multi-Byte-tecken

Vissa tecken använder mer än en byte. Vissa använder två, andra använder tre och vissa använder till och med fyra.

Här är ett exempel på ett dokument som innehåller en massa symboler:

{ "_id" : 2, "data" : "©♡★✪☆" }

Vart och ett av dessa tecken använder mer än en byte. Det betyder att vi måste vara försiktiga när vi extraherar en delsträng. Vi måste vara säkra på att vår utgångspunkt inte börjar halvvägs genom en karaktär. Om det gör det kommer ett fel att uppstå. På samma sätt måste vi se till att vår slutpunkt inte slutar halvvägs genom en karaktär.

Låt oss nu använda $substrBytes utan att göra ett fel:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 2 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            bytes: { $strLenBytes: [ "$data" ] },
            result: { $substrBytes: [ "$data", 0, 5 ] }
          }
     }
   ]
)

Resultat:

{ "data" : "©♡★✪☆", "bytes" : 14, "result" : "©♡" }

Baserat på vår utgångspunkt 0 och vår bytelängd på 5 , får vi två tecken i vår resultatuppsättning. Därför kan vi se att de två första tecknen använder 5 byte.

I det här exemplet använde jag också $strLenBytes för att returnera det totala antalet byte i strängen. Jag gjorde detta främst för att visa att de fem tecknen använder 14 byte (flera byte per tecken).

Här är ett något modifierat exempel som returnerar vart och ett av de två tecknen som returneras:

db.test.aggregate(
   [
     { $match: { _id: { $in: [ 2 ] } } },
     {
       $project:
          {
            _id: 0,
            data: 1,
            r1: { $substrBytes: [ "$data", 0, 2 ] },
            r2: { $substrBytes: [ "$data", 2, 3 ] }
          }
     }
   ]
)

Resultat:

{ "data" : "©♡★✪☆", "r1" : "©", "r2" : "♡" }

Vi kan se att det första tecknet använder två byte och det andra tecknet använder tre.

Fel utgångspunkt

Om din startpunkt är halvvägs genom ett tecken uppstår ett fel.

Exempel:

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

Resultat:

Error: command failed: {
	"ok" : 0,
	"errmsg" : "$substrBytes:  Invalid range, starting index is a UTF-8 continuation byte.",
	"code" : 28656,
	"codeName" : "Location28656"
} : 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

Det här felet talar om för oss att startindexet är en UTF-8-fortsättningsbyte . Med andra ord, vi försökte börja halvvägs genom en karaktär.

Fel slutpunkt

Det är samma sak med slutpunkten. Om din slutpunkt är halvvägs genom ett tecken uppstår ett fel.

Exempel:

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

Resultat:

Error: command failed: {
	"ok" : 0,
	"errmsg" : "$substrBytes:  Invalid range, ending index is in the middle of a UTF-8 character.",
	"code" : 28657,
	"codeName" : "Location28657"
} : 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

Den här gången berättar det för oss att slutindexet är mitt i ett UTF-8-tecken .


  1. Skärning mellan två eller flera sorterade uppsättningar

  2. Mongod klagar på att det inte finns någon /data/db-mapp

  3. Hur gör jag en NOT IN-fråga i Mongo?

  4. Redis Managed Pub/Sub Server