【问题标题】:Is it possible to search for specific scopes with elasticsearch?是否可以使用 elasticsearch 搜索特定范围?
【发布时间】:2016-01-04 03:24:54
【问题描述】:

我需要根据以下范围对文档进行文本搜索:

  1. 整个文档
  2. 章节
  3. 段落
  4. 句子

是否可以对文档进行索引,以便我可以根据此要求过滤查询范围?

根据答案进行编辑

我现在已经创建了以下索引

{
  "settings": {
    "analysis": {
      "analyzer": {
        "folding": {
          "tokenizer": "standard",
          "filter": [ "lowercase", "asciifolding" ]
        }
      }
    }
  },
  "mappings": {
    "books": {
      "properties": {
        "content": {
          "type": "string",
          "fields": {
            "english": {
              "type": "string",
              "analyzer": "english"
            },
            "folded": {
              "type": "string",
              "analyzer": "folding"
            }
          }
        },
        "author": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "language": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "source": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "title": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "fileType": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    },
    "sections": {
      "_parent": { "type": "books" },
      "properties": {
        "content": {
          "type": "string",
          "fields": {
            "english": {
              "type": "string",
              "analyzer": "english"
            },
            "folded": {
              "type": "string",
              "analyzer": "folding"
            }
          }
        },
        "paragraphs": {
          "type": "nested",
          "properties": {
            "paragraph": {
              "properties": {
                "page": { "type": "integer" },
                "number": { "type": "integer" },
                "html_tag": { "type": "string" },
                "content": { "type": "string" }

              }
            }
          }
        },
        "author": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "language": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "source": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "title": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "fileType": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    },
    "messages": {
      "properties": {
        "content": {
          "type": "string",
          "fields": {
            "english": {
              "type": "string",
              "analyzer": "english"
            },
            "folded": {
              "type": "string",
              "analyzer": "folding"
            }
          }
        },
        "paragraphs": {
          "type": "nested",
          "properties": {
            "paragraph": {
              "properties": {
                "page": { "type": "integer" },
                "number": { "type": "integer" },
                "html_tag": { "type": "string" },
                "content": { "type": "string" }

              }
            }
          }
        },
        "author": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "language": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "source": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "title": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        },
        "fileType": {
          "type": "string",
          "fields": {
            "raw": {
              "type": "string",
              "index": "not_analyzed"
            }
          }
        }
      }
    }
  }
}

这给了我以下类型:书籍、部分(父书籍)和消息。 Sections and Messages 有嵌套类型 Paragraphs,我跳过了句子级别。

我现在可以对书籍级别的内容和章节级别的内容执行搜索。这使我可以在段落之间搜索单词。如果我想匹配段落中的两个单词,我也可以直接在段落级别进行搜索。

示例:假设我有以下文档

paragraph 1: It is a beautiful warm day.
paragraph 2: The cloud is clear.

我现在可以在内容级别搜索美丽的 AND 云并取回文档。但是,如果我使用嵌套搜索在段落级别搜索美丽的 AND 云,我不会取回文档,这正是我想要的。

我看到这个解决方案存在的问题是:

  1. 我需要将同一段落索引 3 次。一次在段落级别,一次在内容部分级别,一次在内容书籍级别。
  2. 我不明白 Books 和 Sections 之间的父子关系能给我带来什么好处。我还没有找到任何使用突出显示同时搜索两者的方法。
  3. 我需要一个单独的 Message 类型,它与没有父级的 Section 类型完全相同。有没有办法在没有父母的情况下让孩子打字,这样我就可以避免额外的打字?

【问题讨论】:

标签: elasticsearch


【解决方案1】:

为了实现这一点,您可以索引所有句子,并与句子的单词一起包含有关封闭上下文的信息,即给定句子在哪个段落、章节和书籍中。

然后查询术语将返回句子以及有关章节和书籍的信息。有了这些信息,您就可以知道是哪个句子、段落、章节或书籍。

然后您只需使用您感兴趣的任何范围。

要索引的示例文档:

{
    "book": <book-id>,
    "chapter": <chapter-id>,
    "paragraph": <paragraph-id>,
    "sentence": <sentence-id>,
    "sentence_text": "Here comes the text from a sentence in the indexed book"
}

问题澄清后的附加答案

要实现这一点,您可以使用存储在同一索引中的不同文档类型。然后,您可以使用一个查询来返回可能不同类型的文档(段落、书籍等)。然后通过过滤结果类型,你得到你想要的。这是一个例子:

整本书:

POST /books/book/1
{
    "text": "It is a beautiful warm day. The cloud is clear."
}

第 1 段:

POST /books/para/1
{
    "text": "It is a beautiful warm day."
}

第二段:

POST /books/para/2
{
    "text": "The cloud is clear."
}

查询检索文档:

POST /books/_search
{
    "query": {
        "match": {
           "text": {
                "query": "beautiful cloud",
                "operator": "and"
           }
        }
    }
}

这能解决您的问题吗?

【讨论】:

  • 谢谢。我已经用与您的建议类似的当前解决方案更新了我的问题。如果我理解您的解决方案,唯一的问题是我无法在句子之间搜索单词,因为它们是不同的文档。那是对的吗?您能否看看我目前的解决方案,并就如何改进它提出建议?
  • 我给你正确的答案,因为它与我目前的解决方案非常相似。感谢您的帮助。
【解决方案2】:

另一种选择是拥有一个文档/书,但其中有许多nested documents,这样它们就可以在根级别共享相同的“书”上下文。如果您有一个层次结构(所有句子作为嵌套文档)或更多(capter => paragrap => sentence),这取决于您。单一级别将使查询更易于编写。

{
    "book": 123,
    "author": "Harry",
    "written": 1995,
    "sentences": [
        {
            "chapter": 1,
            "paragraph": 2,
            "sentence": 3,
            "text": "abc def"
        },
        {
            "chapter": 2,
            "paragraph": 3,
            "sentence": 4,
            "text": "ghi jkl"
        },
        { ... }
    ]
}

【讨论】:

  • 谢谢。我目前的解决方案与您的类似。我有一个父书类型和子部分类型。节类型具有嵌套的段落类型。我跳过了句子级别,因为我觉得它会太多。你能看看我在这个解决方案中遇到的问题并帮助我提出任何建议吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2014-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多