Trong MongoDB, $substrBytes
toán tử đường ống tổng hợp trả về chuỗi con của một chuỗi, dựa trên các chỉ mục byte được mã hóa UTF-8 được chỉ định.
Cú pháp
Cú pháp như sau:
{ $substrBytes: [ <string expression>, <byte index>, <byte count> ] }
Ở đâu:
-
<string expression>
là chuỗi. Nó có thể là bất kỳ biểu thức hợp lệ nào miễn là nó phân giải thành một chuỗi. -
<byte index>
là nơi bắt đầu chuỗi con. Nó có thể là bất kỳ biểu thức hợp lệ nào miễn là nó phân giải thành một số nguyên không âm hoặc một số có thể được biểu diễn dưới dạng số nguyên. -
<byte count>
là bao nhiêu byte mà chuỗi con sẽ tiếp tục. Nó có thể là bất kỳ biểu thức hợp lệ nào miễn là nó phân giải thành một số nguyên không âm hoặc một số có thể được biểu diễn dưới dạng số nguyên.
Ví dụ
Hãy tưởng tượng chúng ta có một bộ sưu tập có tên là tests
với tài liệu sau:
{ "_id" : 1, "data" : "Red Firetruck" }
Chúng ta có thể sử dụng $substrBytes
như thế này:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 1 ] } } },
{
$project:
{
_id: 0,
data: 1,
result: { $substrBytes: [ "$data", 0, 3 ] }
}
}
]
)
Kết quả:
{ "data" : "Red Firetruck", "result" : "Red" }
Chỉ mục bắt đầu từ 0 và vì vậy chuỗi con của chúng ta bắt đầu ở đầu chuỗi và tiếp tục trong ba byte.
Trong trường hợp này, chúng tôi đang sử dụng các ký tự tiếng Anh và mỗi ký tự là một byte. Điều này giúp chúng tôi dễ dàng đếm bao nhiêu byte sẽ sử dụng.
Hãy chạy một ví dụ khác:
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()
Kết quả:
{ "data" : "Red Firetruck", "result_1" : "Fire", "result_2" : "truck", "result_3" : "truck" }
Lưu ý trong kết quả thứ ba của chúng tôi, chúng tôi đã chỉ định nhiều byte hơn số byte có sẵn, nhưng nó chỉ trả về tất cả các ký tự về cuối chuỗi.
Ký tự nhiều byte
Một số ký tự sử dụng nhiều hơn một byte. Một số sử dụng hai, một số sử dụng ba và một số thậm chí sử dụng bốn.
Dưới đây là một ví dụ về tài liệu chứa nhiều ký hiệu:
{ "_id" : 2, "data" : "©♡★✪☆" }
Mỗi ký tự này sử dụng nhiều hơn một byte. Điều này có nghĩa là chúng ta cần phải cẩn thận khi trích xuất một chuỗi con. Chúng ta cần chắc chắn rằng điểm xuất phát của chúng ta không bắt đầu giữa chừng cho một nhân vật. Nếu có, một lỗi sẽ xảy ra. Tương tự như vậy, chúng tôi cần đảm bảo rằng điểm kết thúc của chúng tôi không kết thúc giữa chừng cho một nhân vật.
Bây giờ, hãy áp dụng $substrBytes
mà không gây ra lỗi:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
bytes: { $strLenBytes: [ "$data" ] },
result: { $substrBytes: [ "$data", 0, 5 ] }
}
}
]
)
Kết quả:
{ "data" : "©♡★✪☆", "bytes" : 14, "result" : "©♡" }
Dựa trên điểm xuất phát của chúng tôi là 0
và độ dài byte của chúng tôi là 5
, chúng tôi nhận được hai ký tự trong tập kết quả của chúng tôi. Do đó, chúng ta có thể thấy rằng hai ký tự đầu tiên sử dụng 5 byte.
Trong ví dụ này, tôi cũng sử dụng $strLenBytes
để trả về tổng số byte trong chuỗi. Tôi làm điều này chủ yếu để cho thấy rằng năm ký tự sử dụng 14 byte (nhiều byte cho mỗi ký tự).
Dưới đây là một ví dụ được sửa đổi một chút trả về từng ký tự trong số hai ký tự được trả về:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
r1: { $substrBytes: [ "$data", 0, 2 ] },
r2: { $substrBytes: [ "$data", 2, 3 ] }
}
}
]
)
Kết quả:
{ "data" : "©♡★✪☆", "r1" : "©", "r2" : "♡" }
Chúng ta có thể thấy rằng ký tự đầu tiên sử dụng hai byte và ký tự thứ hai sử dụng ba byte.
Điểm xuất phát sai
Nếu điểm xuất phát của bạn được nửa chừng ký tự, thì sẽ xảy ra lỗi.
Ví dụ:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
result: { $substrBytes: [ "$data", 1, 2 ] }
}
}
]
)
Kết quả:
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
Lỗi này cho chúng tôi biết rằng chỉ mục bắt đầu starting index is a UTF-8 continuation byte
. Nói cách khác, chúng tôi đã cố gắng bắt đầu một nửa ký tự.
Điểm cuối sai
Điểm cuối cũng vậy. Nếu điểm kết thúc của bạn ở giữa một ký tự, thì sẽ xảy ra lỗi.
Ví dụ:
db.test.aggregate(
[
{ $match: { _id: { $in: [ 2 ] } } },
{
$project:
{
_id: 0,
data: 1,
result: { $substrBytes: [ "$data", 0, 1 ] }
}
}
]
)
Kết quả:
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
Lần này, nó cho chúng ta biết rằng chỉ mục kết thúc ending index is in the middle of a UTF-8 character
.