【问题标题】:How to format output (Remove session data) of custom cypher query with Neo4j::Session.query如何使用 Neo4j::Session.query 格式化自定义密码查询的输出(删除会话数据)
【发布时间】:2016-06-03 18:26:25
【问题描述】:

我在我的 Rails 应用程序中使用 Neo4jrb/Neo4j-core 进行自定义密码查询。我将此输出用作json。但是,每次我运行查询时

例如:

output_hash = Neo4j::Session.query("Match (n) return n limit 1;")

除了结果之外,我还获得了很多关于 会话 本身的不需要的信息。

每个节点都包含以下内容。

      "session": {
    "connection": {
      "parallel_manager": null,
      "headers": {
        "Content-Type": "application/json",
        "User-Agent": "neo4j-gem/7.0.6 (https://github.com/neo4jrb/neo4j)"
      },
      "params": {},
      "options": {
        "params_encoder": null,
        "proxy": null,
        "bind": null,
        "timeout": null,
        "open_timeout": null,
        "boundary": null,
        "oauth": null
      },
      "ssl": {
        "verify": null,
        "ca_file": null,
        "ca_path": null,
        "verify_mode": null,
        "cert_store": null,
        "client_cert": null,
        "client_key": null,
        "certificate": null,
        "private_key": null,
        "verify_depth": null,
        "version": null
      },
      "default_parallel_manager": null,
      "builder": {
        "handlers": [
          {
            "name": "Faraday::Request::BasicAuthentication",
            "args": [
              "neo4j",
              "root"
            ],
            "block": null
          },
          {
            "name": "FaradayMiddleware::MultiJson::EncodeJson",
            "args": [],
            "block": null
          },
          {
            "name": "FaradayMiddleware::MultiJson::ParseJson",
            "args": [
              {
                "symbolize_keys": true,
                "content_type": "application/json"
              }
            ],
            "block": null
          },
          {
            "name": "Faraday::Adapter::NetHttpPersistent",
            "args": [],
            "block": null
          }
        ],
        "app": {
          "header_value": "Basic bmVvNGo6cm9vdA==",
          "app": {
            "app": {
              "app": {
                "app": {}
              },
              "options": {
                "symbolize_keys": true,
                "content_type": "application/json"
              },
              "content_types": [
                "application/json"
              ]
            }
          }
        }
      },
      "url_prefix": {
        "scheme": "http",
        "user": null,
        "password": null,
        "host": "localhost",
        "port": 7474,
        "path": "/",
        "query": null,
        "opaque": null,
        "fragment": null,
        "parser": {
          "regexp": {
            "SCHEME": "(?-mix:\\A[A-Za-z][A-Za-z0-9+\\-.]*\\z)",
            "USERINFO": "(?-mix:\\A(?:%\\h\\h|[!$&-.0-;=A-Z_a-z~])*\\z)",
            "HOST": "(?-mix:\\A(?:(?<IP-literal>\\[(?:(?<IPv6address>(?:\\h{1,4}:){6}(?<ls32>\\h{1,4}:\\h{1,4}|(?<IPv4address>(?<dec-octet>[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5]|\\d)\\.\\g<dec-octet>\\.\\g<dec-octet>\\.\\g<dec-octet>))|::(?:\\h{1,4}:){5}\\g<ls32>|\\h{,4}::(?:\\h{1,4}:){4}\\g<ls32>|(?:(?:\\h{1,4}:)?\\h{1,4})?::(?:\\h{1,4}:){3}\\g<ls32>|(?:(?:\\h{1,4}:){,2}\\h{1,4})?::(?:\\h{1,4}:){2}\\g<ls32>|(?:(?:\\h{1,4}:){,3}\\h{1,4})?::\\h{1,4}:\\g<ls32>|(?:(?:\\h{1,4}:){,4}\\h{1,4})?::\\g<ls32>|(?:(?:\\h{1,4}:){,5}\\h{1,4})?::\\h{1,4}|(?:(?:\\h{1,4}:){,6}\\h{1,4})?::)|(?<IPvFuture>v\\h+\\.[!$&-.0-;=A-Z_a-z~]+))\\])|\\g<IPv4address>|(?<reg-name>(?:%\\h\\h|[!$&-.0-9;=A-Z_a-z~])*))\\z)",
            "ABS_PATH": "(?-mix:\\A\\/(?:%\\h\\h|[!$&-.0-;=@-Z_a-z~])*(?:\\/(?:%\\h\\h|[!$&-.0-;=@-Z_a-z~])*)*\\z)",
            "REL_PATH": "(?-mix:\\A(?:%\\h\\h|[!$&-.0-;=@-Z_a-z~])+(?:\\/(?:%\\h\\h|[!$&-.0-;=@-Z_a-z~])*)*\\z)",
            "QUERY": "(?-mix:\\A(?:%\\h\\h|[!$&-.0-;=@-Z_a-z~\\/?])*\\z)",
            "FRAGMENT": "(?-mix:\\A(?:%\\h\\h|[!$&-.0-;=@-Z_a-z~\\/?])*\\z)",
            "OPAQUE": "(?-mix:\\A(?:[^\\/].*)?\\z)",
            "PORT": "(?-mix:\\A[\\x09\\x0a\\x0c\\x0d ]*\\d*[\\x09\\x0a\\x0c\\x0d ]*\\z)"
          }
        }
      },
      "proxy": null
    },
    "resource_data": {
      "extensions": {},
      "node": "http://localhost:7474/db/data/node",
      "relationship": "http://localhost:7474/db/data/relationship",
      "node_index": "http://localhost:7474/db/data/index/node",
      "relationship_index": "http://localhost:7474/db/data/index/relationship",
      "extensions_info": "http://localhost:7474/db/data/ext",
      "relationship_types": "http://localhost:7474/db/data/relationship/types",
      "batch": "http://localhost:7474/db/data/batch",
      "cypher": "http://localhost:7474/db/data/cypher",
      "indexes": "http://localhost:7474/db/data/schema/index",
      "constraints": "http://localhost:7474/db/data/schema/constraint",
      "transaction": "http://localhost:7474/db/data/transaction",
      "node_labels": "http://localhost:7474/db/data/labels",
      "neo4j_version": "3.0.1"
    },
    "resource_url": "http://localhost:7474/db/data/"
  }

会话数据似乎包含很多敏感信息,所以我不能直接使用输出。

我想避免这种情况,只获得简单、必要的输出到我的密码查询,而不需要额外的信息。是否有我可以用来完成此操作的配置设置?

谢谢。

更新: 我实际上使用 Neo4jrb/Neo4j(包括 Neo4j-core)作为 ActiveModel 替代项目中的一些基本任务。以及针对主要任务的自定义查询。

进一步检查:

只要定义了一个 ActiveNode 模型,我就会得到一个明确的响应,而无需任何额外的(会话)数据。但只返回模型文件中定义的属性。

class User
    include Neo4j::ActiveNode

    property :name, type: String
    property :email, type: String
end

这对 User 模型工作正常,根据文档,默认情况下忽略模型文件中未声明的任何属性(但存在于数据库中)。

我的问题:我的图有某些节点,这些节点将有许多不同的属性键,这些属性键无法预先硬编码到模型文件中(使用无列数据库的原因)。我无法在模型中声明这些节点的所有属性。

所以我尝试将自定义密码查询作为 Neo4j::Session.query(q) 但 JSON 响应过于杂乱无章地会话数据。使用代码处理此响应会导致代码复杂,因为在结果(节点、边、聚合器)之间包含 会话数据 的方式似乎不一致。

我正在寻找解决方案或出路。

【问题讨论】:

  • 我不完全确定您为什么要获取所有这些数据,但即将到来的 8.0 中有一个设置允许您更改包装方式,包括返回的哈希表示结果
  • 对不起,我昨晚需要快速下线。您说每个节​​点都包含所有这些数据。你是如何获取数据的?它看起来像 JSON 响应,但随后 neo4j / neo4j-core gems 将节点/关系包装在对象中。
  • 非常感谢您让布赖恩回来。我已经用详细信息更新了帖子。是的,它是一个 JSON 响应。当一个模型被声明时,它给了我声明的属性并且没有混乱。当没有模型时,我得到所有属性,但会话数据也很混乱。
  • 对不起,更正一下。我得到一个Enumerator。通过to_a 方法将其转换为结构数组。 [#&lt;struct n=CypherNode xx (70157506237380)&gt;,...] 是数组。在我的应用程序中,我直接执行render json: Enumerator,它将数据转换为 json。此外,json 还包括来自法拉第的数据。也许如果某些变量被传递给 Neo4j-core,它会将它包含在每一行数据中?
  • 我在这里可能超出了我的深度。但是通过源代码,我发现这条线很奇怪,并且是我的问题的潜在原因。 Neo4j-core CypherResponse Class

标签: ruby-on-rails neo4j cypher neo4j.rb


【解决方案1】:

感谢布赖恩的帮助。 总结一下:

输出中的session 键是因为Neo4j-core 尽可能返回相应的对象(节点/边),请参阅源代码中的this line here。 CypherNode 和 CypherRelationship 类都有 @session 变量,当它们的对象转换为 JSON/Hash/YAML 时,session 数据将自动包含在内。

一种选择是编写您自己的自定义方法并扩展类以提供更清晰的 JSON 输出。 Brian 提到即将发布的 8.0 将在响应中提供语法选项。或者您可以在您的应用程序中编写您的自定义代码来处理来自Neo4j-core 的响应。

我最终做了后者如下:

class TestController < ApplicationController

    def test
        q = "Match (n) return n;"
        data = Neo4j::Session.query(q)
        output = clean_response(data)

        render json: output
    end

    private

    def clean_response(data)
        # data = Enumerator
        data = data.map(&:to_h)
        # data = [ { x: => CypherXxxx <Object>},...   ]
        data.map! do |entry|
            hash = JSON.parse(entry.to_json)
            # Clean json of the entry
            entry = delete_keys(hash)
        end
    end

    def delete_keys(hash)
        # Recursive func to delete session/response_hash from a hash of any depth 
        if(hash.class == Hash)
            hash.delete("session") if hash.keys.include?("session")
            hash.delete("response_hash") if hash.keys.include?("response_hash")
            hash.each_value{|value|
              value = delete_keys(value)
            }
        end
    end
end

【讨论】:

    【解决方案2】:

    好吧,好像有几件事情发生了;)

    首先,关于未定义的属性,最近这里实际上有一个问题线程:

    https://github.com/neo4jrb/neo4j/issues/1209

    现在您应该能够使用user._persisted_obj.props 来获取节点的所有属性,即使它们没有在ActiveNode 模型中定义。

    关于 JSON,我想我明白你在说什么。实际上,我认为Enumerator 对呈现为 JSON 的支持不是很好。我以前见过人们有这个问题,但它只是点击了原因。现在,尝试:

    render json: query_result_enumerator.map(&:to_h)
    

    这应该转换为 Hash 对象和 Hash 以及封闭的 node/rel 对象的数组,都应该支持 JSON 化。

    【讨论】:

    • 感谢 ._persisted_obj.props 和 github 问题参考。我可以继续我的工作而不会停滞不前。关于 JSON:它仍然在每一行中包含 session 数据。我相信这是因为session 被自动包含在每一行(节点/边对象)中作为键值对。我看到的唯一解决方案是从 JSON 的每一行中删除 session,但我觉得我不妨看看 gem 是否有问题并尽可能修复它。我会玩弄源代码并回复你。
    • 你是对的。 CypherNodeCypherRelationship、标签等所有类自然都有一个@session 变量。正在转换为 JSON 中的键值对。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-20
    • 2019-11-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多