在Elasticsearch中搜索复杂的嵌套JSON对象

qfe3c7zg  于 2023-04-29  发布在  ElasticSearch
关注(0)|答案(1)|浏览(270)

如何在Elasticsearch中高效地搜索嵌套的JSON对象,并只返回相关数据,而不返回整个文档?
我有一个JSON对象,表示每个用户都将摄取的菜单结构。每个菜单项都有嵌套字段,如“文本”、“URL”、“区域”和“子项”。我希望能够搜索这些领域的任何一个,并返回搜索查询的相关数据。例如,如果我搜索“工作流角色”,我只想返回相关的菜单项,而不是所有额外的数据。
我尝试为菜单对象创建嵌套Map,但是我使用内部命中的查询返回了太多的数据。我也尝试过路径过滤器,但没有找到满意的解决方案。
所以我的问题是
1.在Elasticsearch中摄取深度嵌套的JSON对象以实现高效搜索的最佳方法是什么?
1.对于这样一个深度嵌套的对象,Map应该如何构造?
1.如何编写一个查询,使我可以搜索所有嵌套字段,并只返回搜索查询的相关数据?

下面是需要搜索的JSON对象示例:

[
  {
    "MenuStructure": 0,
    "NavigationLinkId": 0,
    "Children": [
      {
        "MenuStructure": 0,
        "NavigationLinkId": 111,
        "Text": "Bulk Actions",
        "Action": "Index",
        "Controller": "BulkUpload",
        "Area": "Company",
        "Url": "/some-url/bulk-upload",
      }
    ]
  },
  {
    "MenuStructure": 1,
    "NavigationLinkId": 1,
    "Children": [
      {
        "MenuStructure": 1,
        "NavigationLinkId": 2,
        "Text": "Company Config",
        "Area": "Company",
        "Url": "javascript:void(0);",
        "Children": [
          {
            "MenuStructure": 1,
            "NavigationLinkId": 0,
            "Text": "Basic Settings",
            "Url": "javascript:void(0);",
            "Children": [
              {
                "MenuStructure": 1,
                "NavigationLinkId": 60668,
                "Text": "Company Settings",
                "Icon": "fas fa-cogs",
                "Url": "javascript:void(0);",
                "Children": [
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 27,
                    "Text": "Basic Company Information",
                    "Icon": "fa fa-building",
                    "Action": "Index",
                    "Controller": "CompanyProfile",
                    "Area": "Company",
                    "Url": "/some-url/company-profile",
                  },
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 163,
                    "Text": "Reminder Contact Details",
                    "Icon": "fas fa-balance-scale-right",
                    "Url": "/some-url/classic/163",
                  }
                ]
              },
              {
                "MenuStructure": 1,
                "NavigationLinkId": 0,
                "Text": "Dropdown Management",
                "Icon": "fas fa-users-class",
                "Url": "javascript:void(0);",
                "Children": [
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 261,
                    "Text": "Workflow Roles",
                    "Action": "Index",
                    "Controller": "CompanyWorkflowRoles",
                    "Area": "Company",
                    "Url": "/some-url/workflow-roles"
                  },
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 50323,
                    "Text": "Other Dropdowns",
                    "Icon": "fas fa-balance-scale-right",
                    "Url": "/some-url/classic/50323"
                  }
                ]
              },
              {
                "MenuStructure": 1,
                "NavigationLinkId": 50327,
                "Text": "Legislative Configurations",
                "Icon": "fas fa-balance-scale-right",
                "Url": "javascript:void(0);",
                "Children": [
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 244,
                    "Text": "Statistics SA Config",
                    "Url": "/some-url/classic/244"
                  }
                ]
              }
            ]
          },
          
          {
            "MenuStructure": 1,
            "NavigationLinkId": 167,
            "Text": "Security",
            "Icon": "fa fa-lock",
            "Url": "javascript:void(0);",
            "Children": [
              {
                "MenuStructure": 1,
                "NavigationLinkId": 167,
                "Text": "Security",
                "Icon": "fa fa-lock",
                "Url": "javascript:void(0);",
                "Children": [
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 168,
                    "Text": "User Profiles",
                    "Url": "/some-url/classic/168",
                  },
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 169,
                    "Text": "Security Roles",
                    "Url": "/some-url/classic/169",
                  },
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 188,
                    "Text": "User Org. Unit Permissions",
                    "Url": "/some-url/classic/188",
                  },
                  {
                    "MenuStructure": 1,
                    "NavigationLinkId": 60610,
                    "Text": "Activate Users",
                    "Url": "/some-url/classic/60610",
                  }
                ]
              }
            ]
          }
        ]
      }
    ]
  }
]

为了实现这一点,我尝试为菜单对象创建一个嵌套的字段类型Map。以下是一个示例Map:

PUT my-index
{
  "mappings": {
    "properties": {
      "user_id": {
        "type": "keyword"
      },
      "menu": {
        "type": "nested",
        "properties": {
          "MenuStructure": {
            "type": "long"
          },
          "NavigationLinkId": {
            "type": "long"
          },
          "Text": {
            "type": "text"
          },
          "Action": {
            "type": "keyword"
          },
          "Controller": {
            "type": "keyword"
          },
          "Area": {
            "type": "keyword"
          },
          "Url": {
            "type": "keyword"
          },
          "Icon": {
            "type": "keyword"
          },
          "Children": {
            "type": "nested",
            "properties": {
              "MenuStructure": {
                "type": "long"
              },
              "NavigationLinkId": {
                "type": "long"
              },
              "Text": {
                "type": "text"
              },
              "Action": {
                "type": "keyword"
              },
              "Controller": {
                "type": "keyword"
              },
              "Area": {
                "type": "keyword"
              },
              "Url": {
                "type": "keyword"
              },
              "Icon": {
                "type": "keyword"
              },
              "Children": {
                "type": "nested",
                "properties": {
                  "MenuStructure": {
                    "type": "long"
                  },
                  "NavigationLinkId": {
                    "type": "long"
                  },
                  "Text": {
                    "type": "text"
                  },
                  "Action": {
                    "type": "keyword"
                  },
                  "Controller": {
                    "type": "keyword"
                  },
                  "Area": {
                    "type": "keyword"
                  },
                  "Url": {
                    "type": "keyword"
                  },
                  "Icon": {
                    "type": "keyword"
                  },
                  "Children": {
                    "type": "nested",
                    "properties": {
                      "MenuStructure": {
                        "type": "long"
                      },
                      "NavigationLinkId": {
                        "type": "long"
                      },
                      "Text": {
                        "type": "text"
                      },
                      "Action": {
                        "type": "keyword"
                      },
                      "Controller": {
                        "type": "keyword"
                      },
                      "Area": {
                        "type": "keyword"
                      },
                      "Url": {
                        "type": "keyword"
                      },
                      "Icon": {
                        "type": "keyword"
                      },
                      "Children": {
                        "type": "nested",
                        "properties": {
                          "MenuStructure": {
                            "type": "long"
                          },
                          "NavigationLinkId": {
                            "type": "long"
                          },
                          "Text": {
                            "type": "text"
                          },
                          "Action": {
                            "type": "keyword"
                          },
                          "Controller": {
                            "type": "keyword"
                          },
                          "Area": {
                            "type": "keyword"
                          },
                          "Url": {
                            "type": "keyword"
                          },
                          "Icon": {
                            "type": "keyword"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

如何搜索任何子节点的嵌套属性,我尝试了以下和其他一些类似的查询类型:

GET my-index/_search
{
  "query": {   
    "nested": {
      "path": "menu",
      "query": {
        "bool": {
          "must": [
            {"match": 
            {
              "menu.Children.Area": "Company"
            }
            }
          ]
        }
      },
      "inner_hits": {"highlight": {"fields": {"menu.Children.Area": {}}}}
    }
  }
}

上面的查询实际上并不起作用,因为它基本上返回了这么多数据。我只想返回内部点击,例如,如果您搜索'Workflow Roles',则只返回

{
    "MenuStructure": 1,
    "NavigationLinkId": 261,
    "Text": "Workflow Roles",
    "Action": "Index",
    "Controller": "CompanyWorkflowRoles",
    "Area": "Company",
    "Url": "/some-url/workflow-roles"
}

而不是所有的额外数据。我已经尝试了相当多的组合与路径过滤器等。但我想我正在走这条路。

kxkpmulp

kxkpmulp1#

您需要多级嵌套字段(menu +所有Children子字段)并相应地设计您的查询,然后它将按照您的期望工作。
查询的设计方式需要使每个嵌套字段都需要自己的嵌套查询,因此您可能必须执行以下操作:

{
  "query": {
    "bool": {
      "minimum_should_match": 1, 
      "should": [
        {
          "nested": {
            "path": "menu",
            "query": {
              "match": {
                "menu.Text": "Company"
              }
            }
          }
        },
        {
          "nested": {
            "path": "menu.Children",
            "query": {
              "match": {
                "menu.Children.Text": "Company"
              }
            }
          }
        },
        {
          "nested": {
            "path": "menu.Children.Children",
            "query": {
              "match": {
                "menu.Children.Children.Text": "Company"
              }
            }
          }
        },
        ...
      ]
    }
  }
}

相关问题