当前位置: 首页 > 知识库问答 >
问题:

是否可以在 Elasticseach Painless 脚本中转换 JSON 数据,并对其执行进一步的操作?

朱令
2023-03-14

我们有一个大型的 JSON 格式文档语料库,可以搜索以查找模式和历史趋势。Elasticsearch似乎非常适合这个问题。第一个技巧是文档是数以万计的“嵌套”文档(带有标题)的集合。第二个技巧是这些嵌套文档表示具有不同类型的数据。

为了适应这种情况,所有值字段都已“编码”为字符串数组,因此单个整数值已存储在 JSON 中为“[\”1\“]”,浮点数表平展为“[\”123.45\“、\”678.9\“,...]”等。(我们也有字符串数组,不需要转换。虽然这很尴尬,但我认为这将是一个很好的折衷方案,因为Elasticsearch中涉及的其他所有内容似乎都有效。

这里的特殊问题是,这些存储的数据值可能表示一个位域,我们可能需要从中检查一个位的状态。由于此字段将存储为单元素字符串数组,如“[\”14657\“],我们需要将其转换为单个整数,然后将其多次位移到所需的位(或者应用掩码,如果这样的函数可用)。

通过Elasticsearch,我发现我可以嵌入“无痛”脚本,但示例各不相同,我还没有找到一个可以显示如何将任意长度的字符串数组数据字段转换为适当类型的脚本,以供进一步比较。这是我的查询脚本。

{
  "_source" : false,
  "from" : 0, "size" : 10,
  "query": {
    "nested": {
      "path": "Variables",
      "query": {
        "bool": {
          "must": {
            "match": {"Variables.Designation": "Big_Long_Variable_Name"}
          },
          "must_not": {
            "match": {"Variables.Data": "[0]"}
          },
          "filter": {
            "script": {
              "script": {
                "source":
                "
                  def vals = doc['Variables.Data'];
                  return vals[0] != params.setting;
                ",
                "params": {
                  "setting": 3
                }
              }
            }
          }
        }
      },
      "inner_hits": {
        "_source": "Variables.Data"
      }
    }
  }
}

我需要以某种方式将<code>vals</code>变量转换为整数数组,提取第一个值,执行一些位运算,并进行比较以返回true或false。在本例中,我希望能够将“设置”设置为等于我要检查开/关的位位置。

我已经通过 Elasticsearch 完成了练习,发现我需要将 Variables.Data 字段设置为关键字,以便搜索其中的特定值。我意识到这偏离了Elasticsearch的意图,但出于其他原因,我仍然认为这可能是最好的解决方案。我创建了一个新索引,并重新导入了我的测试文档,索引大小增加了约 30%。这是我愿意做出的妥协,如果我能做到这一点的话。

我在无痛中有什么工具来完成这个工作?(或者说,我试图用这个工具来做这件事是不是疯了?)

共有1个答案

郤瀚
2023-03-14

我建议您在 elasticsearch 中尽可能(甚至当没有)提供的类型中对数据进行编码,以充分利用无痛。例如,对于位字符串,您可以将它们编码为1和0的数组,以便使用Painless进行更轻松的操作。

在我看来,无痛仍然很原始。很难调试。很难阅读。很难维护。而且,在无痛中拥有大功能是一个可怕的想法。

为了回答您的问题,您基本上需要使用painless解析数组字符串,并将其放在可用的数据类型中,以便进行所需的比较。例如,对于列表,您可以使用split函数,然后手动将结果中的每个项设置为int、float、string等。。。

在将其添加到脚本字段之前,使用执行API测试小块:

POST /_scripts/painless/_execute
{
  "script": {
    "source": """
    ArrayList arr = []; //to start with
    // use arr.add(INDEX, VALUE) to add after parsing
    """,
    "params": {
      "foo": 100.0,
      "bar": 1000.0
    }
  }
}

另一方面,如果您将数据保存在ElasticSearch提供的数据类型中(请注意,ElasticSearch支持在文档中保存列表),那么这项任务会轻松得多。

例如,不使用my_doc.foo = "[\"123.45\ ",\"678.9\ ",...]"作为以后要解析的字符串,为什么不保存为原生的floats列表而改为像my_doc.foo = [123.45,678.9,...]?

这样,您就避免了解析文本文档所需的不必要的代码

 类似资料:
  • 是否有可能在函数的上下文中解析(实现)一个promise对象?是否有其他方法处理这个问题? UPD:这个代码对我有效。谢了!

  • 问题内容: 我想用PHP重写一个函数(比方说mail()函数),并希望做到这一点,所以当我从现在开始调用mail()时,它将加载我的mail()版本,而不是默认的php版本。这可能在php中吗? 我之所以要这样做,是因为我有成千上万行调用mail()的代码,而我不想重写所有代码。 另外,为了将来参考,在计算机编程中,当您执行此类操作时,它被称为什么? 问题答案: 有一个扩展允许您覆盖功能。它打算用

  • 我正在eclipse中使用模拟器。我在模拟器中提取了大约2200条文本消息/data/data/com.android.providers.telephony/databases/mmssms。从emulator中读取db,并在其中看到文本消息 SQLiteDatabase smsDB=SQLiteDatabase.openDatabase("/data/data/com.android.prov

  • 我正在尝试实现一个永久的工作流,它从阻塞直到消息被传递的活动开始(即Redis的)。一旦完成,我想异步启动一个新的工作流来进行某种处理并立即返回。 我尝试使用子工作流启动处理工作流。我观察到,我的父工作流在子工作流执行之前完成。除非我处理返回的未来,但我真的不想这样做。 正确的方法是什么?是否可以在工作流中启动新的常规工作流?此类操作是作为工作流的一部分还是在活动中实现? 提前谢谢你!

  • 我正在编写一个带有事务回滚的简单json数据库。我需要向一个文件追加一行文本,然后根据追加是否成功,将成功或失败记录到另一个文件。如果需要,第二个文件用于回滚。因此,在继续之前,我需要确定写操作是否成功。 我使用stream.write追加我的文本行,其中包括一个回调,应该验证写操作的成功或失败。 然后我在下面的URL上的NodeJS文档中读到了这个不幸的消息https://nodejs.org/

  • 问题内容: 是否可以在PHP中运行Python脚本并相互传递变量? 我有一堂课,以某种全球性的方式抓取网站获取数据。我想使其变得更加具体,并且已经具有针对多个网站的pythons脚本。 我正在寻找一种将这些内容纳入班级的方法。 两者之间安全可靠的数据传输是否可能?如果是这样的话,要取得这样的成就有多困难? 问题答案: 通常,您可以通过使用通用语言格式并使用和来传递数据来在语言之间进行通信。 PHP