Я пытаюсь динамически построить запрос для ElasticSearch, вот мой код:
import json
query_string = "person human"
query = {}
query['query'] = {}
query['query']['bool'] = {}
query['query']['bool']['must'] = {}
must_string = []
term_string = {}
term_string['term'] = {}
term_string['term']["labels.Name"] = ""
for term in query_string.split():
term_string['term']["labels.Name"] = term
must_string.append(term_string)
query['query']['bool']['must'] = must_string
print(json.dumps(query))
Я ожидал вывод, как это:
{"query": {"bool": {"must": [{"term": {"labels.Name": "person"}}, {"term": {"labels.Name": "human"}}]}}}
но вместо этого я получаю это:
{"query": {"bool": {"must": [{"term": {"labels.Name": "human"}}, {"term": {"labels.Name": "human"}}]}}}
Обратите внимание на дублированное значение в labels.Name
. labels.Name
.
Существует проблема, когда я добавляю в список и перезаписываю предыдущее значение.
Вы добавляете один и тот же словарь в свой список каждый раз. Ссылка на один словарь. Вы можете ссылаться на новый словарь, создавая новый словарь каждый раз:
for term in query_string.split():
term_string = {}
term_string['term'] = {}
term_string['term']["labels.Name"] = ""
term_string['term']["labels.Name"] = term
must_string.append(term_string)
Для построения вложенного словаря я рекомендую вам использовать collections.defaultdict
: см. Defaultdict defaultdict, вложенный.
Проблема заключается не в списке, а в словаре: вы обновляете значение
term_string['term']["labels.Name"]
на каждой итерации цикла for. Вы можете заменить
term_string['term']["labels.Name"] = term
что-то вроде:
term_string = {'term':{'labels.name':term}}
Словарь Python передается по ссылке. Это означает, что при добавлении к must_string
вы действительно добавляете ссылку на словарь term_string
, так что, когда вы изменяете словарь term_string в следующем цикле, он меняет основной словарь, а не только последнюю версию.
Чтобы сделать то, что вы хотите, вам нужно будет создать новый словарь для каждого цикла для добавления, или вы можете сделать deepcopy()
(из библиотеки copy
) вашего словаря, прежде чем добавлять его.