php - 复杂的嵌套数组问题

标签 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;
}

最佳答案

如果您想在单个查询中返回结果,那么您最终会得到该节点的重复数据,在每个单独的行中,该行与该节点有不同的邻接关系...这很好,这就是它的工作原理。

但就目前情况而言,如果该节点上没有邻接,则不会返回节点(因为您使用的是 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/

相关文章:

php - Laravel 请求验证在版本 5.2 中抛出 HttpResponseException

javascript - 打开具有动态值的模态 [symfony2]

javascript - 如何修复我的 CSS 下拉菜单

php - mysql DELETE 查询出现 JOIN 错误...

php - 使用 rowspan 将数据从数据库调用到表中

php - 如何修改外键约束以删除级联

php - 如何使用服务帐户凭据访问 Google 电子表格?

javascript - JsTestDriver 通过 :DOC syntax? 轻松将元素附加到正文

javascript - Gulp 只看主 scss 而不是部分

mysql - 使用 mysql auto_increment 到一个较低的未使用的数字