In MongoDB, de $substrBytes
aggregatiepijplijnoperator retourneert de subtekenreeks van een tekenreeks, gebaseerd op de opgegeven UTF-8-gecodeerde bytes-indexen.
Syntaxis
De syntaxis gaat als volgt:
{ $substrBytes: [ <string expression>, <byte index>, <byte count> ] }
Waar:
<string expression>
is de snaar. Het kan elke geldige uitdrukking zijn, zolang deze maar wordt omgezet in een tekenreeks.<byte index>
is waar de subtekenreeks moet beginnen. Het kan elke geldige uitdrukking zijn, zolang deze maar wordt omgezet in een niet-negatief geheel getal of getal dat kan worden weergegeven als een geheel getal.<byte count>
is hoeveel bytes de substring moet doorgaan. Het kan elke geldige uitdrukking zijn, zolang deze maar wordt omgezet in een niet-negatief geheel getal of getal dat kan worden weergegeven als een geheel getal.
Voorbeeld
Stel je voor dat we een verzameling hebben met de naam tests
met het volgende document:
{ "_id" : 1, "data" : "Red Firetruck" }
We kunnen $substrBytes
. gebruiken zoals dit:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 1 ] } } },
{
$project:
{
_id: 0,
data: 1,
result: { $substrBytes: [ "$data", 0, 3 ] }
}
}
]
)
Resultaat:
{ "data" : "Red Firetruck", "result" : "Red" }
De index begint bij nul, en dus begon onze substring aan het begin van de string en ging door gedurende drie bytes.
In dit geval gebruiken we Engelse karakters en elk karakter is één byte. Dit maakt het voor ons gemakkelijk om te tellen hoeveel bytes we moeten gebruiken.
Laten we nog een voorbeeld geven:
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()
Resultaat:
{ "data" : "Red Firetruck", "result_1" : "Fire", "result_2" : "truck", "result_3" : "truck" }
Merk op dat we in ons derde resultaat meer bytes hebben gespecificeerd dan er beschikbaar waren, maar alle tekens werden teruggestuurd naar het einde van de tekenreeks.
Multi-Byte-tekens
Sommige tekens gebruiken meer dan één byte. Sommigen gebruiken er twee, sommigen gebruiken er drie en sommigen gebruiken er zelfs vier.
Hier is een voorbeeld van een document dat een heleboel symbolen bevat:
{ "_id" : 2, "data" : "©♡★✪☆" }
Elk van deze karakters gebruikt meer dan één byte. Dit betekent dat we voorzichtig moeten zijn bij het extraheren van een subtekenreeks. We moeten er zeker van zijn dat ons startpunt niet halverwege een personage begint. Als dit het geval is, treedt er een fout op. Evenzo moeten we ervoor zorgen dat ons eindpunt niet halverwege een personage eindigt.
Laten we voor nu $substrBytes
. toepassen zonder een fout te veroorzaken:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
bytes: { $strLenBytes: [ "$data" ] },
result: { $substrBytes: [ "$data", 0, 5 ] }
}
}
]
)
Resultaat:
{ "data" : "©♡★✪☆", "bytes" : 14, "result" : "©♡" }
Gebaseerd op ons startpunt van 0
en onze bytelengte van 5
, krijgen we twee tekens in onze resultatenset. Daarom kunnen we zien dat de eerste twee tekens 5 bytes gebruiken.
In dit voorbeeld heb ik ook $strLenBytes
. gebruikt om het totale aantal bytes in de tekenreeks te retourneren. Ik deed dit vooral om aan te tonen dat de vijf karakters 14 bytes gebruiken (meerdere bytes per karakter).
Hier is een enigszins aangepast voorbeeld dat elk van de twee geretourneerde tekens retourneert:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
r1: { $substrBytes: [ "$data", 0, 2 ] },
r2: { $substrBytes: [ "$data", 2, 3 ] }
}
}
]
)
Resultaat:
{ "data" : "©♡★✪☆", "r1" : "©", "r2" : "♡" }
We kunnen zien dat het eerste teken twee bytes gebruikt en het tweede teken drie.
Verkeerd startpunt
Als je startpunt halverwege een teken is, treedt er een fout op.
Voorbeeld:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
result: { $substrBytes: [ "$data", 1, 2 ] }
}
}
]
)
Resultaat:
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
Deze fout vertelt ons dat de starting index is a UTF-8 continuation byte
. Met andere woorden, we probeerden halverwege een personage te beginnen.
Verkeerd eindpunt
Hetzelfde geldt voor het eindpunt. Als je eindpunt halverwege een teken is, treedt er een fout op.
Voorbeeld:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
result: { $substrBytes: [ "$data", 0, 1 ] }
}
}
]
)
Resultaat:
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
Deze keer vertelt het ons dat de ending index is in the middle of a UTF-8 character
.