如何通过Python查询在Elasticsearch的不同字段中找到相等的值?
我在Elasticsearch(+Kibana)中得到了一些值,并想制作一个图,其中某些节点是连接的 我的字段是“prev”和“curr”,表示用户访问的“previous”和“current”页面 例如:如何通过Python查询在Elasticsearch的不同字段中找到相等的值?,python,
elasticsearch,kibana,networkx,Python,
elasticsearch,Kibana,Networkx,我在Elasticsearch(+Kibana)中得到了一些值,并想制作一个图,其中某些节点是连接的 我的字段是“prev”和“curr”,表示用户访问的“previous”和“current”页面 例如: 上一页:主页,当前:唐纳德·特朗普 上一页:其他内部,当前:El_Bienamado 所以我要做的是搜索当前值和先前值相等的值,以便能够连接这些值,并通过Kibana中的Networkx图形进行可视化 我的问题是,我昨天刚开始使用查询语法,不知道这是否可行。 总之,我的目标是制作一个图
- 上一页:主页,当前:唐纳德·特朗普
- 上一页:其他内部,当前:El_Bienamado
- 主页->唐纳德·特朗普->非洲问题->等等
def getPrevList():
previous = []
previousQuery = {
"size": 0,
"aggs": {
"topTerms": {
"terms": {
"field": "prev",
"size": 50000
}
}
}
}
results = es.search(index="wiki", body=previousQuery)["aggregations"]["topTerms"]["buckets"]
for bucket in results:
previous.append({
"prev" : bucket["key"],
"numDocs" : bucket["doc_count"]
})
return previous
prevs=getPrevList()
rowNum = 0;
totalNumReviews=0
for prevDetails in prevs:
rowNum += 1
totalNumDocs += prevDetails["numDocs"]
prevId = prevDetails["prev"]
q = {
"query": {
"bool": {
"must": [
{
"term": {"prev": prevId}
}
]
}
},
"controls": {
"sample_size": 10000,
"use_significance": True
},
"vertices": [
{
"field": "curr",
"size": VERTEX_SIZE,
"min_doc_count": 1
},
{
"field": "prev",
"size": VERTEX_SIZE,
"min_doc_count": 1
}
],
"connections": {
"query": {
"match_all": {}
}
}
}
最后,我将做以下工作:
results = es.transport.perform_request('POST', "/wiki/_xpack/_graph/_explore", body=q)
# Use NetworkX to create a graph of prevs and currs we can analyze
G = nx.Graph()
for node in results["vertices"]:
G.add_node(nodeId(node), type=node["field"])
for edge in results["connections"]:
n1 = results["vertices"][int(edge["source"])]
n2 = results["vertices"][int(edge["target"])]
G.add_edge(nodeId(n1), nodeId(n2))
我从另一个例子中复制了它,它工作得很好,但是我可以看到“连接”对于能够连接顶点很重要
据我所知,我需要查询来找到正确的“prev”字段。
目前,这些控制措施并不重要。
这里是我的复杂部分:我在顶点和连接部分写了什么?我将顶点定义为prev和curr字段是否正确?
在连接查询中:目前我定义了“match_all”,但这显然是不正确的。我需要一个查询,在那里我可以“匹配”这些,其中prev等于curr并连接它们。。但是怎么做
任何提示都将不胜感激!
谢谢你的转发
编辑:
就像@Lupanoide建议的那样,我修改了代码,现在有两个可视化:
第一个是第一个建议的解决方案,它给了我这个图(它的一部分)(matplotlib,不是Kibana):
第二种解决方案看起来更疯狂,更可能是正确的解决方案,但我需要首先在Kibana中将其可视化:
因此,我的脚本的新结尾是:
gq = json.dumps(q)
workspaceID ="/f44c95c0-223d-11e9-b49e-bb0f8e1e7bae" # my v6.4.0 workspace
workspaceUrl = "graph#/workspace/"+workspaceID+"?query=" + urllib.quote_plus(gq)
doc = {
"url": workspaceUrl
}
res = es.index(index=connectionsIndexName, doc_type='task', id=0, body=doc)
我现在唯一的问题是,当我使用Kibana打开URL时,我看不到图形。相反,我得到了“新图表”页面
EDIT2
好的,我发送了这个查询,但是当然光是查询是不够的。我需要传递图形及其连接,对吗?可能吗
多谢各位 编辑:
对于您的用例,您需要找到具有相同prev
值的字段curr
的所有值。因此,您需要对某个页面之后单击的所有页面进行分组。你可以用它来做。
您需要构建一个查询,一方面使用术语聚合返回prev
字段的所有值,然后根据生成的所有curr
值进行聚合:
def getOccurrencyDict():
body = {
"size": 0,
"aggs": {
"getAllThePrevs": {
"terms": {
"field": "prev",
"size": 40000
},
"aggs": {
"getAllTheCurr": {
"terms": {
"field": "curr",
"size": 40000
}
}
}
}
}
}
result = es.search(index="my_index", doc_type="mydoctype", body=body)
然后,您必须构建Networkx
库的classgraph()
所接受的数据结构。因此,您应该构建一个dict of list,然后将该var传递给该方法:
现在将其传递给networkx摄取方法:
G=nx.from_dict_of_lists(dict2Graph)
我还没有测试networkx摄取,所以如果它不起作用,那是因为我们在它里面传递了一个dict of list of dict,而不是dict of list,所以您应该稍微改变一下构建dict2Graph
dict的方式
如果聚合查询的聚合太慢,则应使用prtition。请了解如何在elastic中实现分区聚合
编辑:
阅读networkX文档后,您也可以这样做,而无需创建中间数据结构:
from elasticsearch import Elasticsearch
from elasticsearch.client.graph import GraphClient
es = Elasticsearch()
graph_client = GraphClient(es)
def createGraphInKibana(prev):
q = {
"query": {
"bool": {
"must": [
{
"term": {"prev": prev}
}
]
}
},
"controls": {
"sample_size": 10000,
"use_significance": True
},
"vertices": [
{
"field": "curr",
"size": VERTEX_SIZE,
"min_doc_count": 1
},
{
"field": "prev",
"size": VERTEX_SIZE,
"min_doc_count": 1
}
],
"connections": {
"query": {
"match_all": {}
}
}
}
graph_client.explore(index="your_index", doc_type="your_doc_type", body=q)
G = nx.Graph()
for prev in result["aggregations"]["getAllThePrevs"]["buckets"]:
createGraphInKibana(prev['key'])
for curr in prev["getAllTheCurr"]["buckets"]:
G.add_edge(prev["key"], curr["key"], weight=curr["doc_count"])
又来了@Lupanoide:)我想我说得不够清楚。所以我从来没有一个文档,其中prev和curr是相同的。这只会发生在不同的文档中。例如,我有(上一个,当前)=(A,B)和另一个带有(B,C)的文档,现在我正在搜索一个查询,以便我可以在网络中连接A->B->C。我想,也许我可以找到所有以(A,*)开头的字段,然后从那里看*as(*,#)等等。。是的,prev和curr是关键字数据类型。此外,我没有一个“my_value”,但有近40000个,但我肯定可以对它们进行迭代,对吗?我也编辑了我的答案:)谢谢你的帮助!我知道,答案是完整的,但也许你知道我在编辑部分最后一个问题的答案?@Nin4ikP我很高兴能帮助你。对于最后一个问题,我们可以进行调查。在您尝试从浏览器打开url后-当您说使用Kibana打开url时,您的意思是这样的吗您应该运行tail/var/log/elasticsearch/elasticsearch.log并发布输出,不。我的意思是:我试图将连接图发送到kibana,但我重用了另一个代码,它不适合,因为其他代码发送请求,但我的(或者更好的是你的)聚合了字段。我实际需要的是一个请求,它连接Kibana中与nx图中相同的节点。我现在想弄清楚。如果我知道怎么做,我会告诉你:)看看这里:
from elasticsearch import Elasticsearch
from elasticsearch.client.graph import GraphClient
es = Elasticsearch()
graph_client = GraphClient(es)
def createGraphInKibana(prev):
q = {
"query": {
"bool": {
"must": [
{
"term": {"prev": prev}
}
]
}
},
"controls": {
"sample_size": 10000,
"use_significance": True
},
"vertices": [
{
"field": "curr",
"size": VERTEX_SIZE,
"min_doc_count": 1
},
{
"field": "prev",
"size": VERTEX_SIZE,
"min_doc_count": 1
}
],
"connections": {
"query": {
"match_all": {}
}
}
}
graph_client.explore(index="your_index", doc_type="your_doc_type", body=q)
G = nx.Graph()
for prev in result["aggregations"]["getAllThePrevs"]["buckets"]:
createGraphInKibana(prev['key'])
for curr in prev["getAllTheCurr"]["buckets"]:
G.add_edge(prev["key"], curr["key"], weight=curr["doc_count"])