通过将数组转换为字符串,修复jq“在csv行中无效”

时间:2016-10-06 12:55:24

标签: csv neo4j cypher jq

我尝试使用jq从Neo4j导出CSV,其中包含:

curl --header "Authorization: Basic myBase64hash=" -H accept:application/json -H content-type:application/json \
  -d '{"statements":[{"statement":"MATCH path=(()<--(p:Person)-->(h:House)<--(s:Street)-->(n:Neighbourhood)) RETURN path"}]}' \
  http://localhost:7474/db/data/transaction/commit \
  | jq -r '(.results[0]) | .columns,.data[].row | @csv' > '/tmp/export-subset.csv'

但我收到此错误消息:

jq: error (at <stdin>:0): array ([{"email":"...) is not valid in a csv row

我认为这是因为我有多个电子邮件地址, 是否可以将它们全部放在用逗号分隔的CSV单元格中? 如何使用jq实现这一目标?

修改

这是我的JSON文件的一个示例:

{"results":[{"columns":["path"],"data":[{"row":[[{"email":"gdggdd@gmail.com"},{},{"date_found":"2011-11-29 12:51:14","last_name":"Doe","provider_id":2649,"first_name":"John"},{},{"number":"133","lon":3.21114,"lat":22.8844},{},{"street_name":"Govstreet"},{},{"hood":"Rotterdam"}]],"meta":[[{"id":71390,"type":"node","deleted":false},{"id":226866,"type":"relationship","deleted":false},{"id":63457,"type":"node","deleted":false},{"id":227100,"type":"relationship","deleted":false},{"id":65076,"type":"node","deleted":false},{"id":214799,"type":"relationship","deleted":false},{"id":63915,"type":"node","deleted":false},{"id":226552,"type":"relationship","deleted":false},{"id":71120,"type":"node","deleted":false}]]}]}],"errors":[]}

2 个答案:

答案 0 :(得分:1)

由于您希望按原始顺序排列密钥,请使用keys_unsorted。这应该可以帮助你:

$ jq -r -c '.results[0] | .data[] | .row[]
  | add
  | keys_unsorted as $keys
  | ($keys, [.[$keys[]]])
  | @csv' input.json

(这里的新行主要是为了易读性。)

使用您的说明性输入,输出将是:

"email","date_found","last_name","provider_id","first_name","number","lon","lat","street_name","hood"
"gdggdd@gmail.com","2011-11-29 12:51:14","Doe",2649,"John","133",3.21114,22.8844,"Govstreet","Rotterdam"

当然,在实践中,您可能会有多行数据,因此在这种情况下,您可能需要进行调整以确保标题只打印一次。

答案 1 :(得分:1)

原谅我,但我不熟悉Cypher语法或数据的实际结构,你没有提供太多细节。但根据您的示例输出,我可以收集的每个“行”项似乎与您在Cypher查询中返回的内容相对应。

显然你正在返回path这是一整套节点和关系,而不一定只是你真正感兴趣的数据。

MATCH path=(()<--(p:Person)-->(h:House)<--(s:Street)-->(n:Neighbourhood))
RETURN path

您只需要电子邮件地址,这样您就应该只返回电子邮件。如果我正确理解语法,您可以将其更改为:

MATCH (i)<--(p:Person)-->(h:House)<--(s:Street)-->(n:Neighbourhood)
RETURN i.email

我认为应该会产生类似这样的东西:

{
  "results": [
    {
      "columns": [ "email" ],
      "data": [
        {
          "row": [
            "gdggdd@gmail.com"
          ],
          "meta": [
            {
              "id": 71390,
              "type": "string",
              "deleted": false
            }
          ]
        }
      ]
    }
  ],
  "errors": []
}

然后使用jq将数据导出到csv应该是微不足道的,因为行可以直接转换:

.results[0] | .columns, .data[].row | @csv

另一方面,我的输出实际上看起来可能是完全错误的。因此,只需使用您的示例,如果您只是想要电子邮件,则需要将行映射到电子邮件。

.results[0] | .columns, (.data[].row | map(.[0].email)) | @csv

如果我误解了,如果您打算输出所有值而不仅仅是电子邮件,那么您应该只选择Cypher查询中的值。

MATCH (i)<--(p:Person)-->(h:House)<--(s:Street)-->(n:Neighbourhood)
RETURN i.email, p.date_found, p.last_name, p.provider_id, p.first_name,
    h.number, h.lon, h.lat, s.street_name, n.hood

然后,如果我对输出的假设是正确的,那么普通的jq查询应该会给你你的csv。