Обзор полей JSON
При создании таких приложений, как каталоги товаров, системы управления контентом или системы пользовательских предпочтений, часто требуется хранить гибкие метаданные вместе с векторными вложениями. Атрибуты товаров зависят от категории, предпочтения пользователей меняются со временем, а свойства документов имеют сложную вложенную структуру. Поля JSON в Milvus решают эту проблему, позволяя хранить и запрашивать гибкие структурированные данные без ущерба для производительности.
Что такое поле JSON?
JSON-поле - это тип данных, определяемый схемой (DataType.JSON) в Milvus, который хранит структурированные данные типа "ключ-значение". В отличие от традиционных жестких столбцов базы данных, поля JSON позволяют использовать вложенные объекты, массивы и смешанные типы данных, обеспечивая при этом множество вариантов индексации для быстрых запросов.
Пример структуры поля JSON:
{
"metadata": {
"category": "electronics",
"brand": "BrandA",
"in_stock": true,
"price": 99.99,
"string_price": "99.99",
"tags": ["clearance", "summer_sale"],
"supplier": {
"name": "SupplierX",
"country": "USA",
"contact": {
"email": "support@supplierx.com",
"phone": "+1-800-555-0199"
}
}
}
}
В данном примере metadata - это одно поле JSON, которое содержит смесь плоских значений (например, category, in_stock), массивов (tags) и вложенных объектов (supplier).
Соглашение об именовании: Используйте в ключах JSON только буквы, цифры и символы подчеркивания. Избегайте специальных символов, пробелов и точек, так как они могут вызвать проблемы с разбором в запросах.
Поле JSON против динамического поля
Чаще всего путаница возникает из-за разницы между полем JSON и динамическим полем. Хотя оба они связаны с JSON, они служат разным целям.
В таблице ниже приведены основные различия между полем JSON и динамическим полем:
Характеристика |
JSON-поле |
Динамическое поле |
|---|---|---|
Определение схемы |
Скалярное поле, которое должно быть явно объявлено в схеме коллекции с типом |
Скрытое JSON-поле (с именем |
Случай использования |
Хранение структурированных данных, где схема известна и согласована. |
Хранение гибких, изменяющихся или полуструктурированных данных, которые не вписываются в фиксированную схему. |
Контроль |
Вы контролируете имя и структуру поля. |
Неопределенные поля управляются системой. |
Запрос |
Запрос с использованием имени поля или целевого ключа внутри JSON-поля: |
Запрос напрямую с использованием динамического ключа поля: |
Основные операции
Основной рабочий процесс использования JSON-поля включает его определение в вашей схеме, вставку данных, а затем запрос данных с использованием определенных выражений фильтрации.
Определение поля JSON
Чтобы использовать поле JSON, явно определите его в схеме коллекции при ее создании. В следующем примере показано, как создать коллекцию с полем metadata типа DataType.JSON:
from pymilvus import MilvusClient, DataType
client = MilvusClient(uri="http://localhost:19530") # Replace with your server address
# Create schema
schema = client.create_schema(auto_id=False, enable_dynamic_field=True)
schema.add_field(field_name="product_id", datatype=DataType.INT64, is_primary=True) # Primary field
schema.add_field(field_name="vector", datatype=DataType.FLOAT_VECTOR, dim=5) # Vector field
# Define a JSON field that allows null values
schema.add_field(field_name="metadata", datatype=DataType.JSON, nullable=True)
client.create_collection(
collection_name="product_catalog",
schema=schema
)
В этом примере поле JSON, определенное в схеме коллекции, допускает нулевые значения с nullable=True. Подробнее см. в разделе Nullable & Default.
Вставка данных
После создания коллекции вставьте сущности, содержащие структурированные JSON-объекты, в указанное JSON-поле. Данные должны быть оформлены в виде списка словарей.
entities = [
{
"product_id": 1,
"vector": [0.1, 0.2, 0.3, 0.4, 0.5],
"metadata": { # JSON field
"category": "electronics",
"brand": "BrandA",
"in_stock": True,
"price": 99.99,
"string_price": "99.99",
"tags": ["clearance", "summer_sale"],
"supplier": {
"name": "SupplierX",
"country": "USA",
"contact": {
"email": "support@supplierx.com",
"phone": "+1-800-555-0199"
}
}
}
}
]
client.insert(collection_name="product_catalog", data=entities)
Операции фильтрации
Прежде чем выполнять операции фильтрации для полей JSON, убедитесь, что:
Вы создали индекс для каждого векторного поля.
Коллекция загружена в память.
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type="AUTOINDEX",
index_name="vector_index",
metric_type="COSINE"
)
client.create_index(collection_name="product_catalog", index_params=index_params)
client.load_collection(collection_name="product_catalog")
После выполнения этих требований вы можете использовать приведенные ниже выражения для фильтрации коллекции на основе значений в поле JSON. В этих выражениях фильтрации используется специальный синтаксис пути JSON и специальные операторы.
Фильтрация с помощью синтаксиса пути JSON
Чтобы запросить конкретный ключ, используйте скобочную нотацию для доступа к ключам JSON: json_field_name["key"]. Для вложенных ключей соедините их в цепочку: json_field_name["key1"]["key2"].
Чтобы отфильтровать сущности, для которых category является "electronics":
# Define filter expression
filter = 'metadata["category"] == "electronics"'
client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
Для фильтрации сущностей, в которых вложенный ключ supplier["country"] является "USA":
# Define filter expression
filter = 'metadata["supplier"]["country"] == "USA"'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Фильтрация с помощью операторов, специфичных для JSON
Milvus также предоставляет специальные операторы для запроса значений массивов по определенным ключам полей JSON. Например:
json_contains(identifier, expr): Проверяет, существует ли определенный элемент или подмассив в массиве JSON.json_contains_all(identifier, expr): : Проверяет, что все элементы указанного JSON-выражения присутствуют в полеjson_contains_any(identifier, expr): Фильтрует сущности, в которых хотя бы один член JSON-выражения присутствует в поле.
Чтобы найти продукт, который имеет значение "summer_sale" по ключу tags:
# Define filter expression
filter = 'json_contains(metadata["tags"], "summer_sale")'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Чтобы найти продукт, у которого хотя бы одно из значений "electronics", "new" или "clearance" находится в ключе tags:
# Define filter expression
filter = 'json_contains_any(metadata["tags"], ["electronics", "new", "clearance"])'
res = client.search(
collection_name="product_catalog", # Collection name
data=[[0.1, 0.2, 0.3, 0.4, 0.5]], # Query vector (must match collection's vector dim)
limit=5, # Max. number of results to return
filter=filter, # Filter expression
output_fields=["product_id", "metadata"] # Fields to include in the search results
)
print(res)
Дополнительные сведения об операторах, специфичных для JSON, см. в разделе Операторы JSON.
Далее: Ускорение запросов к JSON
По умолчанию запросы к полям JSON без ускорения выполняют полное сканирование всех строк, что может быть медленным для больших наборов данных. Для ускорения JSON-запросов Milvus предоставляет расширенные функции индексирования и оптимизации хранения.
В таблице ниже приведены их отличия и сценарии наилучшего использования:
Техника |
Лучший для |
Массивы Ускорение |
Примечания |
|---|---|---|---|
Индексирование JSON |
Небольшой набор часто используемых ключей, массивы по определенному ключу массива |
Да (по ключу индексированного массива) |
Необходимо предварительно выбрать ключи, требуется обслуживание при изменении схемы |
Измельчение JSON |
Общее ускорение для многих ключей, гибкость для разнообразных запросов |
Нет (не ускоряет значения внутри массивов) |
Дополнительная конфигурация хранилища, массивы по-прежнему нуждаются в индексе для каждого ключа |
Индекс NGRAM |
Поиск с использованием подстановочных знаков, сопоставление подстрок в текстовых полях |
N/A |
Не для числовых/диапазонных фильтров |
Совет: Вы можете комбинировать эти подходы - например, использовать измельчение JSON для ускорения широких запросов, индексацию JSON для высокочастотных ключей массивов и индексацию NGRAM для гибкого текстового поиска.
Подробности реализации см. в разделе:
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
Существуют ли ограничения на размер поля JSON?
Да. Размер каждого поля JSON ограничен 65 536 байтами.
Поддерживает ли поле JSON установку значения по умолчанию?
Нет, поля JSON не поддерживают значения по умолчанию. Однако при определении поля можно установить значение nullable=True, чтобы разрешить пустые записи.
Подробности см. в разделе Nullable & Default.
Существуют ли какие-либо соглашения об именовании для ключей полей JSON?
Да, чтобы обеспечить совместимость с запросами и индексацией:
Используйте только буквы, цифры и символы подчеркивания в ключах JSON.
Избегайте использования специальных символов, пробелов или точек (
.,/, и т. д.).Несовместимые ключи могут вызвать проблемы с разбором в выражениях фильтров.
Как Milvus обрабатывает строковые значения в полях JSON?
Milvus хранит строковые значения именно в том виде, в каком они представлены во входном JSON-файле, без семантических преобразований. Неправильно заключенные в кавычки строки могут привести к ошибкам при разборе.
Примеры допустимых строк:
"a\"b", "a'b", "a\\b"
Примеры недопустимых строк:
'a"b', 'a\'b'