elasticsearch,kibana,networkx,Python,elasticsearch,Kibana,Networkx" /> elasticsearch,kibana,networkx,Python,elasticsearch,Kibana,Networkx" />

如何通过Python查询在Elasticsearch的不同字段中找到相等的值?

如何通过Python查询在Elasticsearch的不同字段中找到相等的值?,python,elasticsearch,kibana,networkx,Python,elasticsearch,Kibana,Networkx,我在Elasticsearch(+Kibana)中得到了一些值,并想制作一个图,其中某些节点是连接的 我的字段是“prev”和“curr”,表示用户访问的“previous”和“current”页面 例如: 上一页:主页,当前:唐纳德·特朗普 上一页:其他内部,当前:El_Bienamado 所以我要做的是搜索当前值和先前值相等的值,以便能够连接这些值,并通过Kibana中的Networkx图形进行可视化 我的问题是,我昨天刚开始使用查询语法,不知道这是否可行。 总之,我的目标是制作一个图

我在Elasticsearch(+Kibana)中得到了一些值,并想制作一个图,其中某些节点是连接的

我的字段是“prev”和“curr”,表示用户访问的“previous”和“current”页面

例如:

  • 上一页:主页,当前:唐纳德·特朗普
  • 上一页:其他内部,当前:El_Bienamado
所以我要做的是搜索当前值和先前值相等的值,以便能够连接这些值,并通过Kibana中的Networkx图形进行可视化

我的问题是,我昨天刚开始使用查询语法,不知道这是否可行。 总之,我的目标是制作一个图,其中节点连接到一个链,例如:

  • 主页->唐纳德·特朗普->非洲问题->等等
意思是有人按一定的顺序访问了这些页面

我现在尝试的是:

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"])