复杂的嵌套数组问题

时间:2013-03-30 02:29:53

标签: php javascript mysql

我想将数据库中的数据查询到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;
}

1 个答案:

答案 0 :(得分:2)

如果你想在单个查询中返回结果,那么你将得到节点的重复数据,在每个单独的行中,与该节点有明显的邻接...哪个好,这是它的工作原理。

但是当它坐下时,如果该节点上没有相邻性,则不会返回节点(因为您使用的是INNER join。您应该使用LEFT join来包含没有节点的节点相关邻接表的结果。)

通过按节点id排序,我们明确确保所有节点及其邻接关系出现在一起。这可能已经发生了,因为id是你的PK,因此这种排序就是“自动地”发生的。但是ORDER BY nodes.id可以确保这种情况发生,并且让任何看到代码的人都明白你的意图。

另外,因为您要从两个表中返回所有*,所以您会在node.idrelationship.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!

中反映这一点