Postgres相同的JSONB记录不作为eq评估

2024-04-25 20:54:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个存储二维浮点数组的JSONB列。你知道吗

{"field1": [[0.04735202492211838,0.48957828405235093 [0.42866042256355286,0.5729520320892334]], "field2": [[etc.],[etc.]]}

字段(键)始终具有相同的名称,数组(值)始终为[2][2]。你知道吗

问题:假设我使用Npgsql和Newtonsoft.JSON文件具体如下:

using Npgsql;
using NpgsqlTypes;
using Newtonsoft.Json;
...
conn = new NpgsqlConnection(...);
conn.Open();
template = new Dictionary<string, double[,]>();

// Not sure if this assignment actually conforms, just illustrative
template["field1"] = [[0.04735202492211838,0.48957828405235093],[0.42866042256355286,0.5729520320892334]]
template["field2"] = [[etc.],[etc.]] //not actual values of course

using (var cmd = new NpgsqlCommand("UPDATE JSONBTABLE SET JSONB_COL = @j WHERE JSONB_ID = @c", conn))
{
    // Could it be an encoding issue with the string?
    // doesn't makes sense, given impl of JSONB
    string js = JsonConvert.SerializeObject(template);
    cmd.Parameters.AddWithValue("j", NpgsqlDbType.Jsonb, js);
    cmd.Parameters.AddWithValue("c", 1);
    cmd.ExecuteNonQuery();
}

这会按预期更新值,看起来没有什么问题。你知道吗

如果我在Python中进行如下查询,问题就会变得很明显

import psycopg2
from psycopg2.extras import Json
...
conn = psycopg2.connect(...)
cur = conn.cursor()

# for this example, our JSONBTABLE only has the record with the one column
cur.execute(
    """
    SELECT JSONB_COL
    FROM JSONBTABLE
    WHERE JSONB_ID = %s
    """, (1,)
)

cols = {column.name: i for i, column in enumerate(cur.description)}
row = cur.fetchone()

jsonb_dict = row[cols["JSONB_COL"]]

#jsonb_dict["field1"] == [[0.04735202492211838,0.48957828405235093],[0.42866042256355286,0.5729520320892334]]
#jsonb_dict["field2"] == [[etc.],[etc.]]

# Assuming that the JSONBTABLE has a column JSONB_ID as PK
cur.execute(
    """
    SELECT JSONB_ID
    FROM JSONBTABLE
    WHERE JSONB_COL = %s
    """, (Json(jsonb_dict),)
)

# This returns nothing. No match. Nada
cur.fetchone()

如果我现在用Python将JSONB插入到表中,那么查询如上所述,cur.fetchone()将返回id 2,与Python代码中插入的副本的OCRB\u id匹配。插入示例如下:

cur.execute(
    """
    INSERT INTO JSONBTABLE(JSONB_COL)
    VALUES(%s)
    """, (Json(jsonb_dict),)
)
conn.commit()

在python代码中插入一个完全相同的副本后,直观地查看表的结果,就像SELECT JSONB_COL FROM JSONBTABLE一样,它们是相同的。你知道吗

但是Postgres并没有发现它们完全相同,因为下面返回FALSE

SELECT 
  (SELECT JSONB_COL FROM JSONBTABLE where JSONB_ID = 1) = 
  (SELECT JSONB_COL FROM JSONBTABLE where JSONB_ID = 2);

更奇怪的是,它返回TRUE

SELECT 
  (SELECT JSONB_COL->'field1' FROM JSONBTABLE where JSONB_ID = 1) = 
  (SELECT JSONB_COL->'field1' FROM JSONBTABLE where JSONB_ID = 2);

但这会返回FALSE

SELECT 
  (SELECT JSONB_COL->'field2' FROM JSONBTABLE where JSONB_ID = 1) = 
  (SELECT JSONB_COL->'field2' FROM JSONBTABLE where JSONB_ID = 2);

同样,从视觉上看,JSONB_ID = 1JSONB_ID = 2的整个JSONB记录的所有字段都是相同的。我目测了他们每个人。你知道吗


Tags: fromidetccoljsonbconnwhereselect