Запрос соединения в ElasticSearch

Есть ли способ (запрос) присоединиться к 2 JSON ниже в ElasticSearch

{
product_id: "1111",
price: "23.56",
stock: "100"
}

{
product_id: "1111",
category: "iPhone case",
manufacturer: "Belkin"
}

Выше 2 JSON обработаны (введены) в 2 разных типах в Logstash, поэтому их индексы доступны в разных «типах», зарегистрированных в Elasticsearch.

Я хочу присоединиться к 2 JSON в поле product_id.


person Fawad    schedule 24.03.2014    source источник
comment
Может ли кто-нибудь вернуться ко мне по этому поводу?   -  person Fawad    schedule 25.03.2014


Ответы (3)


Это зависит от того, что вы имеете в виду, когда говорите ПРИСОЕДИНЯЙТЕСЬ. Elasticsearch не похож на обычную базу данных, которая поддерживает JOIN между таблицами. Это система текстового поиска, которая управляет документами в индексах.

С другой стороны, вы можете выполнять поиск в одном и том же индексе по нескольким типам, используя поля, общие для каждого типа.

Например, взяв ваши данные, я могу создать индекс с двумя типами и их данными следующим образом:

curl -XPOST localhost:9200/product -d '{
    "settings" : {
        "number_of_shards" : 5
    }
}'

curl -XPOST localhost:9200/product/type1/_mapping -d '{
        "type1" : {
            "properties" : {
                "product_id" : { "type" : "string" },
                "price" : { "type" : "integer" },
                "stock" : { "type" : "integer" }
            }
        }   
}'              

curl -XPOST localhost:9200/product/type2/_mapping -d '{
        "type2" : {
            "properties" : {
                "product_id" : { "type" : "string" },
                "category" : { "type" : "string" },
                "manufacturer" : { "type" : "string" }
            }
        }
}'  

curl -XPOST localhost:9200/product/type1/1 -d '{
        product_id: "1111", 
        price: "23",
        stock: "100"
}'

curl -XPOST localhost:9200/product/type2/1 -d '{
        product_id: "1111",
        category: "iPhone case",
        manufacturer: "Belkin"
}'

Я фактически создал один индекс под названием product с двумя типами type1 и type2. Теперь я могу выполнить следующий запрос, и он вернет оба документа:

curl -XGET 'http://localhost:9200/product/_search?pretty=1' -d '{
    "query": {
        "query_string" : {
            "query" : "product_id:1111"
        }
    }
}'

{
  "took" : 95,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.5945348,
    "hits" : [ {
      "_index" : "product",
      "_type" : "type1",
      "_id" : "1",
      "_score" : 0.5945348, "_source" : {
    product_id: "1111",
    price: "23",
    stock: "100"
}
    }, {
      "_index" : "product",
      "_type" : "type2",
      "_id" : "1",
      "_score" : 0.5945348, "_source" : {
    product_id: "1111",
    category: "iPhone case",
    manufacturer: "Belkin"
}
    } ]
  }
}

Причина в том, что Elasticsearch будет искать все документы в этом индексе независимо от их типа. Это все еще отличается от JOIN в том смысле, что Elasticsearch не собирается делать декартово произведение документов, принадлежащих каждому типу.

надеюсь, это поможет

person isaac.hazan    schedule 25.03.2014
comment
Большое спасибо за ваш ответ, не могли бы вы сказать мне, какое лучшее возможное/альтернативное решение в таком случае. Как вы упомянули выше, у меня есть один индекс «продукт» и 2 типа «тип1» и «тип2» с одним общим полем «продукт_ид» в обоих типах. Теперь, каков возможный вариант для меня, чтобы оба JSON были объединены и проиндексированы в новом индексе или типе в Elasticsearch в случае одного и того же «product_id». К вашему сведению, я использую стек ELK (Elasticsearch, Logstash и Kibana). - person Fawad; 26.03.2014
comment
Я не уверен, что понимаю, чего вы пытаетесь достичь, какова ваша конечная цель? Что вы хотите отобразить в Кибане в конце? - person isaac.hazan; 26.03.2014
comment
Ваш ответ точно полезен. На самом деле @isaac.hazan моя конечная цель — отобразить «product_id», «цена», «запас», «категория» и «производитель» в одном событии в Кибане. - person Fawad; 26.03.2014
comment
Чтобы проголосовать за ваш ответ, мне нужно 15 репутации, но мне всего около трех дней в Stake Overflow :( - person Fawad; 26.03.2014
comment
Что касается вашей конечной цели, я не думаю, что это возможно как встроенная функция. Я имел дело с такими же проблемами в другом проекте, и я преодолел это, разработав верхний слой, который принимает 2 события, объединяет их и сохраняет в эластичном поиске как одно событие. При этом помните, что в Kibana, если вы запрашиваете только индекс без типа, вы получите весь набор данных, что технически означает, что вы сможете продемонстрировать некоторый контроль, но я согласен, что это не идеально, например, для гистограммы как у вас будет 2 события вместо 1. - person isaac.hazan; 26.03.2014
comment
не могли бы вы рассказать мне, как мы можем объединить 2 события и сохранить их в Elasticsearch как одно событие, вы используете для этого logstash? - person Fawad; 26.03.2014
comment
Никакой logstash, насколько я знаю, этого не делает. Для этого я использую Elasticsearch JAVA API. - person isaac.hazan; 26.03.2014

Ответ isaac.hazan работает довольно хорошо, но я хотел бы добавить несколько моментов, которые помогли мне в такой ситуации:

Я попал на эту страницу, когда пытался решить аналогичную проблему, поскольку мне приходилось исключать несколько записей одного индекса на основе документов другого индекса. Отсутствие взаимосвязей — один из основных недостатков неструктурированных баз данных.

Страница документации по elasticsearch на странице Обработка отношений многое объясняет.

Для управления реляционными данными в Elasticsearch используются четыре распространенных метода:

  • Соединения на стороне приложения
  • Денормализация данных
  • Вложенные объекты
  • Родительско-детские отношения

Часто окончательное решение требует сочетания нескольких из этих методов.

В основном я использовал вложенные объекты и соединения на стороне приложения. Хотя использование одного и того же имени поля может на мгновение решить проблему, я думаю, что лучше переосмыслить и создать наиболее подходящее сопоставление для вашего приложения.

Например, вы можете обнаружить, что хотите перечислить все товары, цена которых превышает x, или перечислить все товары, которых больше нет на складе. Чтобы справиться с такими сценариями, полезно, если вы используете одно из решений, упомянутых выше.

person ystark    schedule 30.03.2016

Чтобы выполнить объединение в Elasticsearch, взгляните на плагин Siren Federate. Он добавляет возможности объединения, расширяя собственный синтаксис запросов Elasticsearch.

https://siren.io/federate/

person user3165256    schedule 29.07.2020