从mysql检索数组数据的最佳方法是什么

hpxqektj  于 2021-06-18  发布在  Mysql
关注(0)|答案(1)|浏览(519)

我在mysql(实际上是mariadb)数据库中存储这样的对象/数据结构:

{
  idx: 7,
  a: "content A",
  b: "content B",
  c: ["entry c1", "entry c2", "entry c3"]
}

为了存储它,我使用了两个表,非常类似于这个答案中描述的方法:https://stackoverflow.com/a/17371729/3958875

表1:

+-----+---+---+
| idx | a | b |
+-----+---+---+

表2:

+------------+-------+
| owning_obj | entry |
+------------+-------+

然后做了一个视图把它们连接在一起,所以我得到:

+-----+------------+------------+-----------+
| idx | a          | b          | c         |
+-----+------------+------------+-----------+
|   7 | content A1 | content B1 | entry c11 |
|   7 | content A1 | content B1 | entry c21 |
|   7 | content A1 | content B1 | entry c31 |
|   8 | content A2 | content B2 | entry c12 |
|   8 | content A2 | content B2 | entry c22 |
|   8 | content A2 | content B2 | entry c32 |
+-----+------------+------------+-----------+

我的问题是怎样才能把它恢复到我的对象形式(e、 g.我想要一个上面指定的对象类型数组(包含idx在5到20之间的所有条目)
有两种方法我可以想到,但似乎都不是很有效。
首先,我们可以将整个表发送回服务器,它可以制作一个hashmap,其中键是主键或其他一些唯一的索引,然后收集不同的c列,然后用这种方式重建它,但这意味着它必须发送大量重复数据,并且在服务器上重建需要更多的内存和处理时间。如果我们有多个数组,或者数组中有数组,这种方法也不会很容易扩展。
第二种方法是做多个查询,过滤 Table 1 并获取所需的idx列表,然后为每个idx发送一个查询 Table 2 哪里 owning_obj =当前idx。这意味着要发送更多的查询。
这两种选择似乎都不是很好,所以我想知道是否有更好的方法。目前我在想它可能是 JSON_OBJECT() ,但我不知道怎么做。
这似乎是一个常见的情况,但我似乎找不到确切的措辞来寻找得到答案。
ps:与mysql/mariadb接口的服务器是用rust编写的,但不要认为这与这个问题有关

w8rqjzmb

w8rqjzmb1#

你可以用 GROUP_CONCAT 把所有的 c 值转换为逗号分隔的字符串。

SELECT t1.idx, t1.a, t1.b, GROUP_CONCAT(entry) AS c
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON t1.idx = t2.owning_obj
GROUP BY t1.idx

然后在php中分解字符串:

$result_array = [];
while ($row = $result->fetch_assoc()) {
    $row['c'] = explode(',', $row['c']);
    $result_array[] = $row;
}

但是,如果条目可能很长,请确保增加 group_concat_max_len .
如果您使用的是mysql 8.0,那么也可以使用 JSON_ARRAYAGG() . 这将创建 entry 值,可以使用 json_decode() . 这样安全一点,因为 GROUP_CONCAT() 如果任何一个值包含逗号,都会出错。您可以更改分隔符,但需要一个永远不会出现在任何值中的分隔符。不幸的是,这不是在马里亚德。

相关问题