如何使用Python的Weaviate库create_object方法解决“属性值类型不匹配”错误

问题现象与诊断

当开发者使用weaviate.Client.create_object()方法时,最常见的错误之一是属性值类型不匹配。系统会返回类似这样的错误信息:"Property 'age' expected type 'number' but got 'string'"。这种类型不匹配通常发生在以下场景:

  • JSON序列化过程中自动类型转换
  • 从外部数据源(如CSV)导入未清洗的数据
  • 动态语言类型系统导致的隐式转换
  • Weaviate类模式(Schema)定义与实际数据不一致

根本原因分析

Weaviate采用强类型模式系统,在创建类(Class)时必须明确定义每个属性的数据类型。常见的数据类型包括:


{
  "classes": [{
    "class": "Person",
    "properties": [
      {"name": "name", "dataType": ["text"]},
      {"name": "age", "dataType": ["int"]},  # 明确要求整数类型
      {"name": "birthDate", "dataType": ["date"]}
    ]
  }]
}

当Python字典中的值与模式定义不符时,就会触发类型校验错误。例如传递"age": "25"(字符串)而非"age": 25(整数)。

解决方案

1. 预处理数据验证

创建自定义验证器,确保数据符合模式要求:


def validate_object(schema: dict, obj: dict) -> dict:
    type_map = {
        "int": int,
        "text": str,
        "boolean": bool,
        "number": (int, float)
    }
    
    validated = {}
    for prop, value in obj.items():
        expected_type = schema[prop]["dataType"][0]
        if not isinstance(value, type_map[expected_type]):
            try:
                validated[prop] = type_map[expected_type](value)
            except (ValueError, TypeError):
                raise ValueError(f"无法转换 {prop} 值到 {expected_type}")
        else:
            validated[prop] = value
    return validated

2. 使用Pydantic模型

结合Pydantic实现运行时类型检查:


from pydantic import BaseModel, validator

class PersonModel(BaseModel):
    name: str
    age: int
    
    @validator('age', pre=True)
    def convert_age(cls, v):
        return int(v) if str(v).isdigit() else v

person = PersonModel(name="Alice", age="25")  # 自动转换类型
client.create_object("Person", person.dict())

3. 模式同步策略

实施模式版本控制,确保客户端与服务端同步:


def ensure_schema(client, current_schema):
    remote_schema = client.schema.get()
    if remote_schema != current_schema:
        client.schema.delete_all()
        client.schema.create(current_schema)

高级技巧

对于复杂数据类型处理:

  • 日期时间转换:使用datetime.isoformat()处理日期属性
  • 地理坐标:将GeoJSON转换为Weaviate支持的格式
  • 数组类型:确保数组元素类型一致

from datetime import datetime

data = {
    "eventDate": datetime.now().isoformat(),  # 转换为ISO8601字符串
    "locations": {
        "type": "Point",
        "coordinates": [52.3667, 4.8945]
    }
}

错误监控建议

建立完善的错误处理机制:

  1. 记录失败的创建操作及其原始数据
  2. 实现自动重试机制(带指数退避)
  3. 使用Sentry等工具监控类型错误
  4. 定期审计模式与数据的匹配度

通过实施这些解决方案,开发者可以显著减少create_object方法的类型相关错误,提高数据导入的可靠性。