Как отформатировать вывод (удалить данные сеанса) пользовательского запроса шифра с Neo4j::Session.query

Я использую Neo4jrb/Neo4j-core для пользовательских шифровальных запросов в моем приложении Rails. Я использую этот вывод как 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) в качестве замены ActiveModel для нескольких основных задач в этом проекте. И пользовательские запросы для основных задач.

Дальнейшая проверка:

Пока модель ActiveNode определена, я получаю четкий ответ без каких-либо дополнительных (сеансовых) данных. Но возвращаются только свойства, определенные в файле модели.

class User
    include Neo4j::ActiveNode

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

Это нормально работает для модели User, любые свойства, не объявленные в файле модели (но присутствующие в базе данных), по умолчанию игнорируются в соответствии с документацией.

Моя проблема: у моего графа есть определенные узлы, которые будут иметь много разных ключей свойств, которые нельзя заранее жестко закодировать в файл модели (причина использования БД без столбцов). Я не могу объявить все свойства этих узлов в модели.

Поэтому я пытаюсь выполнить пользовательский запрос шифрования как Neo4j::Session.query(q), но ответ JSON слишком хаотичен с данными сеанса. Обработка этого ответа с кодом приводит к запутанному коду, потому что кажется, что не существует согласованного способа, которым данные сеанса включаются между результатами (узлами, ребрами, агрегаторами).

Я ищу решение или выход.

2 ответа

Спасибо Брайан за вашу помощь. Чтобы подвести итог:

session ключ в выходе, потому что Neo4j-core по возможности возвращает соответствующий объект (узел / ребро), обратитесь к этой строке здесь в исходном коде. Оба класса CypherNode и CypherRelationship имеют переменную @session, и когда их объекты преобразуются в JSON/Hash/YAML, session данные включаются автоматически.

Одним из вариантов является написание собственных пользовательских методов и расширение класса для более чистого вывода JSON. Брайан упоминает, что в следующем выпуске 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

Хорошо, похоже, что может быть несколько вещей, происходящих;)

Во-первых, что касается неопределенных свойств, на самом деле здесь недавно был поток вопросов об этом:

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 должны поддерживать JSONified.

Другие вопросы по тегам