我想将数据库中的数据查询到 json 数组中,最终在 JavaScript 中生成力导向图。 Json 数组应该是这样的。然而,节点可以有多个邻接关系,也可以没有,我如何查询一个 json 数组,其中邻接部分因节点而异,并且能够根据节点拥有的邻接数量进行调整?
Var JSON =[
{
"adjacencies": [
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
}
],
"data": {
"$color": "#416D9C",
"$type": "star"
},
"id": "graphnode5",
"name": "graphnode5"
},
];
或者他们可以拥有
Var JSON =[
{
"adjacencies": [
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
},
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
},
{
"nodeTo": "graphnode9",
"nodeFrom": "graphnode5",
"data": {}
}
],
"data": {
"$color": "#416D9C",
"$type": "star"
},
"id": "graphnode5",
"name": "graphnode5"
},
];
或者他们不能有任何
Var JSON =[
{
"adjacencies": [],
"data": {
"$color": "#416D9C",
"$type": "star"
},
"id": "graphnode5",
"name": "graphnode5"
},
];
这是我到目前为止的尝试,但是这只产生一个只允许一个邻接关系的 json,如何设置一个 Json 查询来调整节点拥有的邻接关系数量?虽然只加载一次数据和 id 部分但允许改变邻接关系?
这是我的数据库结构
nodes Relationships
----- -------------
id int(11), id int(11),
name varchar(35), goingto int(11), //this is the destination node from the id relation
color varchar(7), data varchar(0) null
type varchar (12), Foreign key (id) references nodes(id)
Primary key (id)
engine = innodb
这是我的尝试
function getjson(){
$db = adodbConnect();
$query = "SELECT nodes.*, relationships.* FROM nodes inner JOIN relationships ON nodes.id = relationships.id";
$result = $db -> Execute($query);
while($row=$result->FetchRow())
{
$id= (float)$row['id'];
$name = $row['name'];
$color1 = $row['color'];
$type1 = $row['type'];
$to= (float)$row['goingto'];
$thumb =$row['thumb']; //image path
$array[] = array(
"adjacencies" => array( array(
"nodeTo" => "$to",
"nodeFrom" => "$id",
"data" => array() )),
"data" => array(
"$"."color" => $color1,
"$"."type" => $type1 ),
"id" => $id,
"name" => "<img src='".$thumb."' height='25' width='25' alt='root'/><label>".$name."</label>");
}
$json = json_encode($array);
print "$json";
//return $json;
}
最佳答案
如果您想在单个查询中返回结果,那么您最终会得到该节点的重复数据,在每个单独的行中,该行与该节点有不同的邻接关系...这很好,这就是它的工作原理。
但就目前情况而言,如果该节点上没有邻接,则不会返回节点(因为您使用的是 INNER join
。您应该使用 LEFT join
来包含相关节点没有结果的节点)邻接表)。
按节点排序id
,我们明确确保所有节点及其邻接点都分组在一起。这可能已经发生了,因为 id
是你的pk,因此排序是“自动”以这种方式发生的。但是一个ORDER BY nodes.id
确保这种情况发生,并使查看代码的任何人都清楚您的意图。
此外,因为您要返回所有内容 *
从这两个表中,您将在 node.id
上出现列名称冲突。和relationship.id
。理想情况下,您应该明确命名您的列以避免这种情况,以便您在 PHP 中获得可预测的结果。
所以你的 SQL 可能看起来更像:
SELECT
n.id as n_id,
n.name,
n.color,
n.type,
r.id as r_id,
r.goingto,
r.data
FROM
nodes n
LEFT JOIN relationships r
ON n.id = r.id
ORDER BY
n.id
这将返回一个类似于以下内容的结果集:
n_id | name | color | type | r_id | goingto | data
------+-------+--------+-------+------+---------+-----------
1 | node1 | red | type1 | 1 | 5 | stuff
1 | node1 | red | type1 | 2 | 6 | morestuff
2 | node2 | blue | type2 | 3 | 10 | whatever
3 | node3 | green | type3 | null | null | null
4 | node4 | orange | type4 | 4 | 20 | xxx1
4 | node4 | orange | type4 | 5 | 21 | xxx2
4 | node4 | orange | type4 | 6 | 22 | xxx3
etc...
(即假设节点 1 有两个关系,节点 2 有 1 个关系,节点 3 没有关系,节点 4 有 3 个关系)。
然后,构建数组的代码只需要迭代结果,仅当当前记录的节点与前一个记录的节点不同时构建新节点(即我们依赖 ORDER BY node.id
来“按顺序收集”特定节点的所有信息)。
这段代码尚未经过测试,但我认为意图很明确,您应该能够根据需要对其进行修改 - 但它基本上只是实现了上述内容。
替换您的while
循环所有这些。
$previd = -1;
while($row=$result->FetchRow())
{
$id= (float)$row['n_id']; // <--- note change from 'id' to 'n_id'
$name = $row['name'];
$color1 = $row['color'];
$type1 = $row['type'];
$to= (float)$row['goingto'];
$thumb =$row['thumb']; //image path
// Is this row the start of a new node?
if ($previd != $id) {
// Yes, new node. Record our new node id, for future new node checks.
$previd = $id;
// Store the previous node we've already built, now that it's complete (but only if there was a previous node!)
if ($previd != -1) {
$array.push($node);
}
// Start our new node off, ready to accept adjacencies
$node = array(
"adjacencies" => array(),
"data" => array(
"$"."color" => $color1,
"$"."type" => $type1
),
"id" => $id,
"name" => "<img src='".$thumb."' height='25' width='25' alt='root'/><label>".$name."</label>");
}
// Any adjacency for this node, on this row?
if ($to != null) { // <-- Not sure about this line!
// Yes there is, so create the new adjacency record and add it to the current node's adjacency array.
$node["adjacencies"].push(
array(
"nodeTo" => "$to",
"nodeFrom" => "$id",
"data" => array()
)
);
}
}
我不确定 $to
中如何表示“无邻接” - 即如果这将是“空”或什么。我将其留给您进行测试,但足以说明您需要在 if ($to != null) { // <-- Not sure about this line!
行中反射(reflect)这一点
关于php - 复杂的嵌套数组问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15714275/