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

2024-10-03 09:07:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Elasticsearch(+Kibana)中有一些值,我想制作一个图,其中某些节点是连接在一起的。在

我的字段是“prev”和“curr”,指示用户访问的“prev”和“current”页面。在

例如:

  • 上一页:主页,本刊:唐纳德·特朗普
  • 上一页:其他内部,货币:El嫒Bienamado
  • 。。。在

所以我要做的是搜索值,其中current等于previous,以便能够连接这些值并通过Kibana中的Networkx图形可视化。在

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

  • 主页面->;Donald\u Trump->;Problems\u in_Afrika->;等

意思是有人按一定的顺序访问这些页面。在

我现在尝试的是:

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": {}
            }
        }
    }

最后,我要做的是:

^{pr2}$

我从另一个例子中复制了它,效果很好,但是我可以看到“连接”对于连接顶点非常重要。在

据我所知,我需要查询来找到正确的“prev”字段。 目前这些控制措施并不重要。 对我来说,复杂的部分来了:我在顶点和连接部分写了什么?我把顶点定义为prev和curr字段是正确的吗? 在connections查询中:目前我定义了“match_all”,但这显然是不正确的。我需要一个查询,在那里我可以“匹配”这些,其中prev等于curr并连接它们。。但怎么办??在

任何提示都将不胜感激! 谢谢你。在

编辑

就像@Lupanoide建议的那样,我修改了代码,现在有了两个可视化效果: 第一个是第一个建议的解决方案,它给出了这个图(它的一部分)(matplotlib,而不是Kibana):

dict2Graph

第二种解决方案看起来更疯狂,更可能是正确的解决方案,但我需要首先在Kibana中将其形象化:

two for-loops

我的新剧本到此结束:

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时,我看不到图形。取而代之的是“新图表”页面。在

编辑2 好吧,我发送查询,但当然光是查询是不够的。我需要传递图和它的连接,对吗?有可能吗?在

非常感谢!在


Tags: ingtfieldsizeindexdocbucketcount
1条回答
网友
1楼 · 发布于 2024-10-03 09:07:49

编辑: 对于您的用例,您需要使用相同的prev值查找字段{}的所有值。因此,您需要按某个页面后单击的所有页面进行分组。你可以用terms aggregation来完成。 您需要构建一个查询,一方面使用术语聚合返回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库的class Graph()接受的数据结构。因此,您应该构建list的dict,然后将该var传递给fromdictoflist方法:

^{pr2}$

现在将其传递给networkx摄取方法:

^{3}$

我还没有测试networkx摄取,所以如果它不起作用,那是因为我们在里面传递了dict-of-list-of-dict,而不是list-of-dict,所以您应该稍微改变一下构建dict2Graphdict的方式

如果聚合查询的聚合太慢,则应使用prtition。请read here如何以弹性方式到达分区聚合

编辑:

在阅读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"])

相关问题 更多 >