도서 요약 / / 2022. 12. 22. 20:22

08. Adding Bool Logic to Queries

complete guide to elasticsearch를 정리한 자료입니다.
https://www.udemy.com/course/elasticsearch-complete-guide/

94. compound query 소개

95. boolean 로직으로 쿼리

GET recipe/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "ingredients.name": "parmesan"
          }
        },
        {
          "range": {
            "preparation_time_minutes": {
              "lte": 15
            }
          }
        }
      ]
    }
  }
}

range쿼리는 filter로 동작하므로 아래와 같이 filter로 변경하자.

GET recipe/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "ingredients.name": "parmesan"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "preparation_time_minutes": {
              "lte": 15
            }
          }
        }
      ]
    }
  }
}

match, match_not, should, filter 모두 포함

GET recipe/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "ingredients.name": "parmesan"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "ingredients.name": "tuna"
          }
        }
      ],
      "should": [
        {
          "match": {
            "ingredients.name": "parsley"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "preparation_time_minutes": {
              "lte": 15
            }
          }
        }
      ]
    }
  }
}

위의 쿼리에서 parmesan은 포함해야하고 tuna는 포함되지 않는 것을 검색한다.
또한 parsley를 좋아해서 우선순위(score)를 높이기 위해 should를 사용한다. parsely가 없는 값도 결과로 나온다.

Bool 쿼리에서 match, filter가 없이 should를 사용하면 적어도 하나의 값이 매칭이 되어야 한다.

GET recipe/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "ingredients.name": "pasta"
          }
        }
      ],
      "should": [
        {
          "match": {
            "ingredients.name": "parmesan"
          }
        }
      ]
    }
  }
}

위의 쿼리에서 pasta가 포함된 것을 찾고 parmesan이 포함되어 있으면 우선순위를 높여준다. (parmesan이 없어도 pasta만 있으면 검색이 된다.)

하지만 아래 쿼리는 must와 filter가 없기 때문에 parmesan이 포함된 결과만 가져온다.

GET recipe/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "ingredients.name": "parmesan"
          }
        }
      ]
    }
  }
}

96. named 쿼리로 bool 쿼리 디버깅

GET recipe/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "ingredients.name": {
              "query": "parmesan",
              "_name": "parmesan_must"
            }
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "ingredients.name": {
              "query": "tuna",
              "_name": "tuna_must_not"
            }
          }
        }
      ],
      "should": [
        {
          "match": {
            "ingredients.name": {
              "query": "parsley",
              "_name": "parsley_should"
            }
          }
        }
      ],
      "filter": [
        {
          "range": {
            "preparation_time_minutes": {
              "lte": 15,
              "_name": "prep_time_filter"
            }
          }
        }
      ]
    }
  }
}

결과

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 2.1580405,
    "hits" : [
      {
        "_index" : "recipe",
        "_type" : "_doc",
        "_id" : "10",
        "_score" : 2.1580405,
        "_source" : {
          "title" : "Penne With Hot-As-You-Dare Arrabbiata Sauce",
          "description" : """Exceedingly simple in concept and execution, arrabbiata sauce is tomato sauce with the distinction of being spicy enough to earn its "angry" moniker. Here's how to make it, from start to finish.""",
          "preparation_time_minutes" : 15,
          "servings" : {
            "min" : 4,
            "max" : 4
          },
          "steps" : [
            "In a medium saucepan of boiling salted water, cook penne until just short of al dente, about 1 minute less than the package recommends.",
            "Meanwhile, in a large skillet, combine oil, garlic, and pepper flakes. Cook over medium heat until garlic is very lightly golden, about 5 minutes. (Adjust heat as necessary to keep it gently sizzling.)",
            "Add tomatoes, stir to combine, and bring to a bare simmer. When pasta is ready, transfer it to sauce using a strainer or slotted spoon. (Alternatively, drain pasta through a colander, reserving 1 cup of cooking water. Add drained pasta to sauce.)",
            "Add about 1/4 cup pasta water to sauce and increase heat to bring pasta and sauce to a vigorous simmer. Cook, stirring and shaking the pan and adding more pasta water as necessary to keep sauce loose, until pasta is perfectly al dente, 1 to 2 minutes longer. (The pasta will cook more slowly in the sauce than it did in the water.)",
            "Continue cooking pasta until sauce thickens and begins to coat noodles, then remove from heat and toss in cheese and parsley, stirring vigorously to incorporate. Stir in a drizzle of fresh olive oil, if desired. Season with salt and serve right away, passing more cheese at the table."
          ],
          "ingredients" : [
            {
              "name" : "Kosher salt"
            },
            {
              "name" : "Penne pasta",
              "amount" : 450,
              "unit" : "grams"
            },
            {
              "name" : "Extra-virgin olive oil",
              "amount" : 3,
              "unit" : "tbsp"
            },
            {
              "name" : "Clove garlic",
              "amount" : 1,
              "unit" : "pcs"
            },
            {
              "name" : "Crushed red pepper"
            },
            {
              "name" : "Can whole peeled tomatoes",
              "amount" : 400,
              "unit" : "grams"
            },
            {
              "name" : "Finely grated Parmesan cheese",
              "amount" : 60,
              "unit" : "grams"
            },
            {
              "name" : "Minced flat-leaf parsley leaves",
              "amount" : 1,
              "unit" : "handful"
            }
          ],
          "created" : "2017-04-27T15:14:52Z",
          "ratings" : [
            1.5,
            2.0,
            4.0,
            3.5,
            3.0,
            5.0,
            1.5
          ]
        },
        "matched_queries" : [
          "prep_time_filter",
          "parmesan_must",
          "parsley_should"
        ]
      },
      {
        "_index" : "recipe",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.3788301,
        "_source" : {
          "title" : "Fast and Easy Pasta With Blistered Cherry Tomato Sauce",
          "description" : "Cherry tomatoes are almost always sweeter, riper, and higher in pectin than larger tomatoes at the supermarket. All of these factors mean that cherry tomatoes are fantastic for making a rich, thick, flavorful sauce. Even better: It takes only four ingredients and about 10 minutes, start to finish — less time than it takes to cook the pasta you're gonna serve it with.",
          "preparation_time_minutes" : 12,
          "servings" : {
            "min" : 4,
            "max" : 6
          },
          "steps" : [
            "Place pasta in a large skillet or sauté pan and cover with water and a big pinch of salt. Bring to a boil over high heat, stirring occasionally. Boil until just shy of al dente, about 1 minute less than the package instructions recommend.",
            "Meanwhile, heat garlic and 4 tablespoons (60ml) olive oil in a 12-inch skillet over medium heat, stirring frequently, until garlic is softened but not browned, about 3 minutes. Add tomatoes and cook, stirring, until tomatoes begin to burst. You can help them along by pressing on them with the back of a wooden spoon as they soften.",
            "Continue to cook until sauce is rich and creamy, about 5 minutes longer. Stir in basil and season to taste with salt and pepper.",
            "When pasta is cooked, drain, reserving 1 cup of pasta water. Add pasta to sauce and increase heat to medium-high. Cook, stirring and tossing constantly and adding reserved pasta water as necessary to adjust consistency to a nice, creamy flow. Remove from heat, stir in remaining 2 tablespoons (30ml) olive oil, and grate in a generous shower of Parmesan cheese. Serve immediately, passing extra Parmesan at the table."
          ],
          "ingredients" : [
            {
              "name" : "Dry pasta",
              "amount" : 450,
              "unit" : "grams"
            },
            {
              "name" : "Kosher salt"
            },
            {
              "name" : "Cloves garlic",
              "amount" : 4,
              "unit" : "pcs"
            },
            {
              "name" : "Extra-virgin olive oil",
              "amount" : 90,
              "unit" : "ml"
            },
            {
              "name" : "Cherry tomatoes",
              "amount" : 750,
              "unit" : "grams"
            },
            {
              "name" : "Fresh basil leaves",
              "amount" : 30,
              "unit" : "grams"
            },
            {
              "name" : "Freshly ground black pepper"
            },
            {
              "name" : "Parmesan cheese"
            }
          ],
          "created" : "2017-03-29T14:43:21Z",
          "ratings" : [
            4.5,
            5.0,
            3.0,
            4.5
          ]
        },
        "matched_queries" : [
          "prep_time_filter",
          "parmesan_must"
        ]
      }
    ]
  }
}

97. match 쿼리는 어떻게 동작하는가?

GET recipe/_search
{
  "query": {
    "match": {
      "title": "pasta carbonar"
    }
  }
}

위의 쿼리는 실제로 아래와 같이 동작하다.

GET recipe/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "title": "pasta"
          }
        },
        {
          "term": {
            "title": "carbonara"
          }
        }
      ]
    }
  }
}

다음 쿼리를 실행하자.

GET recipe/_search
{
  "query": {
    "match": {
      "title": {
        "query": "pasta carbonar",
        "operator": "and"
      }
    }
  }
}

위는 쿼리는 아래와 같이 동작한다.

GET recipe/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "title": "pasta"
          }
        },
        {
          "term": {
            "title": "carbonara"
          }
        }
      ]
    }
  }
}
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유