You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Npgsql调用PostgreSQL时jsonb #>操作符报错,如何正确传参?

解决Npgsql调用PostgreSQL jsonb操作符的类型不匹配问题

这个错误的核心原因很明确:PostgreSQL的#>操作符要求右侧参数是text数组类型(对应你在DataGrip里写的'{inner_id}',这是PostgreSQL的数组字面量,会被解析为text[]),但你在C#里直接传递了普通字符串,Npgsql默认把它识别为text类型,导致数据库找不到匹配的操作符,所以报错operator does not exist: jsonb #> text。

下面给你两种可行的解决方案:

方案1:正确传递text[]类型的路径参数

直接把SearchField参数转换成PostgreSQL识别的text[]类型,同时注意把SearchValue转成jsonb类型(因为#>返回的是jsonb,两边类型要匹配):

修改你的C#代码如下:

public IQueryable<CustomerForPartnerApiServiceModel> GetCustomerBySearchField(Advertiser advertiser, string searchValue) {
    var rawSql = @" 
select distinct ""Customers"".""CustomerId"" as ""CustomerId"", 
       ""Customers"".""FcmRegistrationId"" as ""FcmRegistrationId"", 
       ""Customers"".""FCMServerKey"" as ""FCMServerKey"", 
       ""Customers"".""AppId"" as ""AppId"" 
from ""CustomerEvents"" 
inner join ""Customers"" on ""CustomerEvents"".""CustomerId"" = ""Customers"".""CustomerId"" 
where ""Customers"".""AdvertiserId"" = @AdvertiserId 
  and ""Data"" #> @SearchField = @SearchValue::jsonb";

    // 处理advertiser.SearchField:如果是类似"{inner_id}"的字符串,先转成string数组
    var searchPathArray = advertiser.SearchField
        .Trim('{', '}')
        .Split(',', StringSplitOptions.RemoveEmptyEntries)
        .Select(s => s.Trim())
        .ToArray();

    var res = _applicationDbContext.BySearchFieldCustomerApiModels.FromSql(rawSql, 
        // 指定参数类型为text数组
        new NpgsqlParameter("SearchField", NpgsqlDbType.Array | NpgsqlDbType.Text) { Value = searchPathArray },
        // 指定SearchValue为jsonb类型
        new NpgsqlParameter("SearchValue", NpgsqlDbType.Jsonb) { Value = searchValue },
        new NpgsqlParameter<int>("AdvertiserId", advertiser.AdvertiserId));
    return res;
}

关键细节说明:

  • 如果你的advertiser.SearchField本来就是数组格式(比如直接存储的是["inner_id"]这样的字符串数组),可以跳过字符串分割的步骤,直接传入数组即可。
  • 加上@SearchValue::jsonb是为了确保比较两边的类型一致,避免出现jsonb = text的类型不匹配错误。

方案2:改用JsonPath语法(PostgreSQL 12+适用)

如果你的PostgreSQL版本是12或以上,可以用更直观的JsonPath语法,参数直接传递字符串路径(比如'$.inner_id'),不需要处理数组:

修改SQL语句和参数如下:

public IQueryable<CustomerForPartnerApiServiceModel> GetCustomerBySearchField(Advertiser advertiser, string searchValue) {
    // 假设advertiser.SearchField现在是类似"$.inner_id"的JsonPath字符串
    var rawSql = @" 
select distinct ""Customers"".""CustomerId"" as ""CustomerId"", 
       ""Customers"".""FcmRegistrationId"" as ""FcmRegistrationId"", 
       ""Customers"".""FCMServerKey"" as ""FCMServerKey"", 
       ""Customers"".""AppId"" as ""AppId"" 
from ""CustomerEvents"" 
inner join ""Customers"" on ""CustomerEvents"".""CustomerId"" = ""Customers"".""CustomerId"" 
where ""Customers"".""AdvertiserId"" = @AdvertiserId 
  and jsonb_path_query(""Data"", @SearchPath) = @SearchValue::jsonb";

    var res = _applicationDbContext.BySearchFieldCustomerApiModels.FromSql(rawSql, 
        new NpgsqlParameter("SearchPath", advertiser.SearchField),
        new NpgsqlParameter("SearchValue", NpgsqlDbType.Jsonb) { Value = searchValue },
        new NpgsqlParameter<int>("AdvertiserId", advertiser.AdvertiserId));
    return res;
}

这种方式更符合现代json查询的习惯,路径格式也更容易理解和维护。

内容的提问来源于stack exchange,提问作者Aleksej_Shherbak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:50:36