2013-01-31 125 views
7

我是Elastic Search和非SQL范例的新手。 我一直在关注ES教程,但有一件事我不能投入工作。在弹性搜索上查询多级嵌套字段

在以下代码中(我使用PyES与ES进行交互),我创建了一个带有嵌套字段(主题)的单个文档,其中包含另一个嵌套字段(概念)。

from pyes import * 

conn = ES('127.0.0.1:9200') # Use HTTP 

# Delete and Create a new index. 
conn.indices.delete_index("documents-index") 
conn.create_index("documents-index") 

# Create a single document. 
document = { 
    "docid": 123456789, 
    "title": "This is the doc title.", 
    "description": "This is the doc description.", 
    "datepublished": 2005, 
    "author": ["Joe", "John", "Charles"], 
    "subjects": [{ 
        "subjectname": 'subject1', 
        "subjectid": [210, 311, 1012, 784, 568], 
        "subjectkey": 2, 
        "concepts": [ 
            {"name": "concept1", "score": 75}, 
            {"name": "concept2", "score": 55} 
            ] 
       }, 
       { 
        "subjectname": 'subject2', 
        "subjectid": [111, 300, 141, 457, 748], 
        "subjectkey": 0, 
        "concepts": [ 
            {"name": "concept3", "score": 88}, 
            {"name": "concept4", "score": 55}, 
            {"name": "concept5", "score": 66} 
            ] 
       }], 
    } 


# Define the nested elements. 
mapping1 = { 
      'subjects': { 
       'type': 'nested' 
      } 
     } 
mapping2 = { 
      'concepts': { 
       'type': 'nested' 
      } 
     } 
conn.put_mapping("document", {'properties': mapping1}, ["documents-index"]) 
conn.put_mapping("subjects", {'properties': mapping2}, ["documents-index"]) 


# Insert document in 'documents-index' index. 
conn.index(document, "documents-index", "document", 1) 

# Refresh connection to make queries. 
conn.refresh() 

我能够查询科目嵌套领域:

query1 = { 
    "nested": { 
     "path": "subjects", 
     "score_mode": "avg", 
     "query": { 
      "bool": { 
       "must": [ 
        { 
         "text": {"subjects.subjectname": "subject1"} 
        }, 
        { 
         "range": {"subjects.subjectkey": {"gt": 1}} 
        } 
       ] 
      } 
     } 
    } 
} 


results = conn.search(query=query1) 
for r in results: 
    print r # as expected, it returns the entire document. 

,但我无法弄清楚如何查询基于概念嵌套场。

ES documentation指的是

多级嵌套自动支撑,并且检测到的,从而导致在其内嵌套查询 自动匹配相关 嵌套级(而不是根),如果它在另一个嵌套存在查询。

所以,我tryed建立具有以下格式的查询:

query2 = { 
     "nested": { 
      "path": "concepts", 
      "score_mode": "avg", 
      "query": { 
       "bool": { 
        "must": [ 
         { 
          "text": {"concepts.name": "concept1"} 
         }, 
         { 
          "range": {"concepts.score": {"gt": 0}} 
         } 
        ] 
       } 
      } 
     } 
} 

其返回0的结果。

我找不出什么是缺少的,我还没有发现任何基于两层嵌套的查询的例子。

回答

12

好吧,尝试组合的提示音后,我终于用下面的查询得到它:

query3 = { 
    "nested": { 
     "path": "subjects", 
     "score_mode": "avg", 
     "query": { 
      "bool": { 
       "must": [ 
        { 
         "text": {"subjects.concepts.name": "concept1"} 
        } 
       ] 
      } 
     } 
    } 
} 

因此,嵌套路径属性(学科)始终是相同的,不管嵌套的属性级别如何,并且在查询定义中我使用了属性的完整路径(subject.concepts.name)。

+0

因为我只使用一个布尔条件,更正确的查询定义将使用 “query”:{“text”:{“subjects.concepts.name”:“concept1”}} – JCJS

1

在黑暗中拍摄,因为我没有尝试过这个人,但你有没有尝试完全合格的路径概念?

query2 = { 
     "nested": { 
      "path": "subjects.concepts", 
      "score_mode": "avg", 
      "query": { 
       "bool": { 
        "must": [ 
         { 
          "text": {"subjects.concepts.name": "concept1"} 
         }, 
         { 
          "range": {"subjects.concepts.score": {"gt": 0}} 
         } 
        ] 
       } 
      } 
     } 
    } 
+0

我张贴我的答案,没有刷新页面,我没有看到你的答案。 几乎就是这样,路径值只应该是“主体”。 – JCJS

0

我对JCJS的回答有一些疑问。为什么你的映射不应该这样?

mapping = { 
    "subjects": { 
     "type": "nested", 
     "properties": { 
      "concepts": { 
       "type": "nested" 
      } 
     } 
    } 
} 

我试着定义两个类型映射可能不起作用,但是是一个压扁的数据;我认为我们应该嵌套在嵌套属性..

最后...如果我们用这个映射嵌套查询应该是这样的...

{ 
    "query": { 
     "nested": { 
      "path": "subjects.concepts", 
      "query": { 
       "term": { 
        "name": { 
         "value": "concept1" 
        } 
       } 
      } 
     } 
    } 
} 

它是利用full path的路径属性的重要...但不适用于术语密钥可以是全路径或相对路径。