MongoDB zawiera $strLenBytes
i $strLenCP
operatorów w swojej strukturze potoku agregacji. Operatorzy ci robią podobną, ale nieco inną rzecz. W niektórych przypadkach oba zwrócą dokładnie ten sam wynik, podczas gdy w innych wyniki będą się różnić.
Oto krótki przegląd różnicy między tymi dwoma operatorami.
Różnica
Oto definicja każdego operatora:
$strLenBytes
zwraca liczbę bajtów zakodowanych w UTF-8 w określonym ciągu$strLenCP
zwraca liczbę punktów kodowych UTF-8 w określonym ciągu.
Zwróć uwagę na różnicę pogrubioną czcionką. Jeden zwraca liczbę bajtów , druga zwraca liczbę punktów kodowych .
Podczas pracy z ciągami w języku angielskim liczba bajtów będzie zwykle taka sama jak liczba punktów kodowych. Każdy punkt kodowy użyje jednego bajtu.
Ale podczas pracy z innymi językami, które używają innego bloku Unicode, może się okazać, że liczba bajtów wzrośnie do dwóch lub trzech bajtów. Dotyczy to również pracy z innymi punktami kodu Unicode, takimi jak symbole, emoji itp. W niektórych przypadkach pojedynczy znak może mieć 4 bajty.
Przykład
Załóżmy, że mamy kolekcję o nazwie unicode
z następującymi dokumentami:
{ "_id" : 1, "data" : "é" } { "_id" : 2, "data" : "©" } { "_id" : 3, "data" : "℘" }
A teraz zastosujmy oba $strLenBytes
i $strLenCP
do pola danych:
db.unicode.aggregate(
[
{
$project:
{
_id: 0,
data: 1,
strLenCP: { $strLenCP: "$data" },
strLenBytes: { $strLenBytes: "$data" }
}
}
]
)
Wynik:
{ "data" : "é", "strLenCP" : 1, "strLenBytes" : 2 } { "data" : "©", "strLenCP" : 1, "strLenBytes" : 2 } { "data" : "℘", "strLenCP" : 1, "strLenBytes" : 3 }
Widzimy, że wszystkie znaki używają tylko jednego punktu kodowego, ale pierwszy dokument używa dwóch bajtów, a pozostałe dwa dokumenty używają trzech bajtów.
Znaki angielskie
Załóżmy, że mamy kolekcję o nazwie english
z następującymi dokumentami:
{ "_id" : 1, "data" : "Fast dog" } { "_id" : 2, "data" : "F" } { "_id" : 3, "data" : "a" } { "_id" : 4, "data" : "s" } { "_id" : 5, "data" : "t" } { "_id" : 6, "data" : " " } { "_id" : 7, "data" : "d" } { "_id" : 8, "data" : "o" } { "_id" : 9, "data" : "g" }
A teraz zastosujmy oba $strLenBytes
i $strLenCP
do pola danych:
db.english.aggregate(
[
{
$project:
{
_id: 0,
data: 1,
strLenCP: { $strLenCP: "$data" },
strLenBytes: { $strLenBytes: "$data" }
}
}
]
)
Wynik:
{ "data" : "Fast dog", "strLenCP" : 8, "strLenBytes" : 8 } { "data" : "F", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : "a", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : "s", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : "t", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : " ", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : "d", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : "o", "strLenCP" : 1, "strLenBytes" : 1 } { "data" : "g", "strLenCP" : 1, "strLenBytes" : 1 }
W takim przypadku wszystkie znaki używają jednego punktu kodowego i jednego bajtu.
Znaki tajskie
Oto przykład, który używa znaków tajskich, aby zademonstrować, że nie wszystkie języki używają jednego bajtu na punkt kodowy.
Załóżmy, że mamy kolekcję o nazwie thai
z następującymi dokumentami:
{ "_id" : 1, "data" : "ไม้เมือง" } { "_id" : 2, "data" : "ไ" } { "_id" : 3, "data" : "ม้" } { "_id" : 4, "data" : "เ" } { "_id" : 5, "data" : "มื" } { "_id" : 6, "data" : "อ" } { "_id" : 7, "data" : "ง" }
Oto, co się dzieje, gdy zastosujemy oba $strLenBytes
i $strLenCP
do pola danych:
db.thai.aggregate(
[
{
$project:
{
_id: 0,
data: 1,
strLenCP: { $strLenCP: "$data" },
strLenBytes: { $strLenBytes: "$data" }
}
}
]
)
Wynik:
{ "data" : "ไม้เมือง", "strLenCP" : 8, "strLenBytes" : 24 } { "data" : "ไ", "strLenCP" : 1, "strLenBytes" : 3 } { "data" : "ม้", "strLenCP" : 2, "strLenBytes" : 6 } { "data" : "เ", "strLenCP" : 1, "strLenBytes" : 3 } { "data" : "มื", "strLenCP" : 2, "strLenBytes" : 6 } { "data" : "อ", "strLenCP" : 1, "strLenBytes" : 3 } { "data" : "ง", "strLenCP" : 1, "strLenBytes" : 3 }