flowpack / elasticsearch-contentrepositoryadaptor
该软件包提供在Neos.ContentRepository.Search之上使用Elasticsearch的功能
Requires
- php: ^7.3 || ^8.0
- ext-json: *
- flowpack/elasticsearch: ^5.0 || dev-master
- neos/content-repository: ^7.0 || ^8.0 || dev-master
- neos/content-repository-search: ^4.0 || dev-master
- neos/eel: ^7.0 || ^8.0 || dev-master
- neos/flow: ^7.0 || ^8.0 || dev-master
- neos/fluid-adaptor: ^7.0 || ^8.0 || dev-master
- neos/utility-arrays: ^7.0 || ^8.0 || dev-master
- dev-master
- 8.5.0
- 8.4.0
- 8.3.0
- 8.2.1
- 8.2.0
- 8.1.1
- 8.1.0
- 8.0.6
- 8.0.5
- 8.0.4
- 8.0.3
- 8.0.2
- 8.0.1
- 8.0.0
- 7.1.0
- 7.0.x-dev
- 7.0.9
- 7.0.8
- 7.0.7
- 7.0.6
- 7.0.5
- 7.0.4
- 7.0.3
- 7.0.2
- 7.0.1
- 7.0.0
- 6.0.x-dev
- 6.0.6
- 6.0.5
- 6.0.4
- 6.0.3
- 6.0.2
- 6.0.1
- 6.0.0
- 5.0.x-dev
- 5.0.6
- 5.0.5
- 5.0.4
- 5.0.3
- 5.0.2
- 5.0.1
- 5.0.0
- 4.1.2
- 4.1.1
- 4.1.0
- 4.0.x-dev
- 4.0.7
- 4.0.6
- 4.0.5
- 4.0.4
- 4.0.3
- 4.0.2
- 4.0.1
- 4.0.0
- 3.1.2
- 3.1.1
- 3.1.0
- 3.0.x-dev
- 3.0.6
- 3.0.5
- 3.0.4
- 3.0.3
- 3.0.2
- 3.0.1
- 3.0.0
- 2.0.x-dev
- 2.0.7
- 2.0.6
- 2.0.5
- 2.0.4
- 2.0.3
- 2.0.2
- 2.0.1
- 2.0.0
- 1.2.x-dev
- 1.2.0
- 1.0.0
- 0.5.0
- dev-bugfix/do-not-fail-on-empty-resource-stream
This package is auto-updated.
Last update: 2024-09-14 09:35:23 UTC
README
Neos Elasticsearch适配器
此项目将Neos内容存储库连接到Elasticsearch,实现两个主要功能
- 通过任意查询在Fusion / Eel中查找节点
- 页面和其他文档(当然包括全文)的全文索引
本文档结构如下
安装
composer require 'flowpack/elasticsearch-contentrepositoryadaptor'
// Not required, but can be used to learn how to integration the flowpack/elasticsearch-contentrepositoryadaptor in your project
composer require 'flowpack/searchplugin'
确保按照以下说明更新<your-elasticsearch>/config/elasticsearch.yml
;然后启动Elasticsearch。
最后,运行./flow nodeindex:build
,并将搜索插件添加到您的页面。它应该“直接工作”。
相关软件包
- Neos.ContentRepository.Search:为搜索Neos内容存储库节点提供通用功能。不包含搜索后端。
- Flowpack.ElasticSearch:为与Elasticsearch一起工作提供通用代码
- Flowpack.ElasticSearch.ContentRepositoryAdaptor:此软件包
- Flowpack.SimpleSearch.ContentRepositoryAdaptor:备选搜索后端(可替换此软件包使用);将搜索索引存储在SQLite中
- Flowpack.SearchPlugin:Neos的搜索插件
Elasticsearch和Neos兼容性
以下矩阵显示了本软件包与Elasticsearch和Neos版本的兼容性
当前驱动器接口尚未标记为API,可以更改以适应未来的需求。
Elasticsearch配置文件elasticsearch.yml
以下一般配置建议可以使您的生活更轻松
# the following settings secure your cluster cluster.name: [PUT_YOUR_CUSTOM_NAME_HERE] node.name: [PUT_YOUR_CUSTOM_NAME_HERE] network.host: _local_
根据您的Elasticsearch版本,您可能需要向Elasticsearch配置文件<your-elasticsearch>/config/elasticsearch.yml
添加特定配置。
命令
建立索引
节点索引会实时更新,但在开发过程中您需要频繁更新它。
在映射更新时,您需要重新索引所有节点。不用担心在生产环境中这样做;系统会透明地创建一个新的索引,将其完全填充,然后当一切正常时,更改索引别名。
./flow nodeindex:build
如果在开发过程中,您只想索引少量节点,可以使用"限制"功能
./flow nodeindex:build --limit 20
清理旧索引
为了删除旧的、未使用的索引,您应该时不时地使用此命令
./flow nodeindex:cleanup
调试命令
以下命令旨在在配置和开发您的搜索时进行调试。
./flow nodeindexmapping:indices
显示项目维度预设与结果索引名称之间的映射。
./flow nodeindexmapping:mapping
显示为NodeTypes创建的映射。
./flow nodetype:showIndexableConfiguration
显示节点类型列表及其是否配置为可索引。
./flow search:viewnode <nodeIdentifier> [<dimensionCombinationAsJson>] [<field>]
显示给定节点索引的所有内容。
./flow search:fulltext
执行全文搜索并显示结果。
配置
索引设置
如果您想在更详细级别上微调索引和映射,可以按照以下方式操作。
配置索引名称
如果您需要在同一Elasticsearch服务器上运行多个(不同的)neos实例,您需要更改每个项目的配置/Settings.yaml中的indexName。
因此,./flow nodeindex:build
或 ./flow nodeindex:cleanup
不会覆盖您的其他站点索引。
Neos: ContentRepository: Search: elasticSearch: indexName: useMoreSpecificIndexName
如果您使用多个客户端配置,请更改 default 键,位于 indexes 下方。
按索引配置
您可以使用索引前缀为所有索引设置一个默认配置。
Flowpack: ElasticSearch: indexes: default: # Configuration bundle name neoscontentrepository: # The index prefix name, must be the same as in the Neos.ContentRepository.Search.elasticSearch.indexName setting settings: index: number_of_shards: 1 number_of_replicas: 0
按维度配置
由于Neos内容存储库的每个维度组合都会创建一个索引,因此您可以分别配置每个维度组合的索引行为。
注意:默认配置和按维度组合配置不会合并。如果找到维度组合的配置,则使用此配置。
Flowpack: ElasticSearch: indexes: default: 'neoscontentrepository-0359ed5c416567b8bc2e5ade0f277b36': # The hash specifies the dimension combination settings: index: number_of_shards: 1 number_of_replicas: 0 analysis: filter: elision: type: 'elision' articles: [ 'l', 'm', 't', 'qu', 'n', 's', 'j', 'd' ] analyzer: custom_french_analyzer: tokenizer: 'letter' filter: [ 'asciifolding', 'lowercase', 'french_stem', 'elision', 'stop' ] tag_analyzer: tokenizer: 'keyword' filter: [ 'asciifolding', 'lowercase' ]
可以使用CLI命令显示系统中哪些维度组合可用以及它们用哪些散列值标识
./flow nodeindexmapping:indices
按属性(索引字段)的配置
然后,您可以在每个字段级别上更改分析器;例如,使用以下片段在NodeTypes.yaml中重新配置_all字段。通常,这通过在[nodeType].search.elasticSearchMapping
中定义全局映射来实现。
'Neos.Neos:Node': search: elasticSearchMapping: myProperty: analyzer: custom_french_analyzer
从索引中排除节点类型
默认情况下,索引过程处理所有节点类型,但您可以在您的Settings.yaml中更改此设置
Neos: ContentRepository: Search: defaultConfigurationPerNodeType: '*': indexed: true 'Neos.Neos:FallbackNode': indexed: false 'Neos.Neos:Shortcut': indexed: false 'Neos.Neos:ContentCollection': indexed: false
您需要显式配置单个节点类型(此功能不会检查超级类型配置)。但是,您可以使用特殊符号来配置完整命名空间,例如,Acme.AcmeCom:*
将应用于Acme.AcmeCom
命名空间中的所有节点类型。按照此顺序使用最具体的配置。
- 节点类型名称(
Neos.Neos:Shortcut
) - 完整命名空间符号(
Neos.Neos:*
) - 通配符(
*
)
高级索引配置
按数据类型索引配置
默认配置支持大多数用例,通常可能不需要更改,因为此包为所有Neos数据类型提供了合理的默认值。
属性索引配置在两个地方。默认的数据类型配置在Settings.yaml
中的Neos.ContentRepository.Search.defaultConfigurationPerType
内部。此外,可以使用NodeTypes.yaml
中的properties.[....].search
路径来覆盖此配置。
此配置包含两部分
- 在
elasticSearchMapping
下方,可以定义Elasticsearch属性映射。 - 在
indexing
下方,需要指定一个Eel表达式,该表达式在索引之前处理值。它有权访问当前的value
和当前的node
。
示例(来自默认配置)
# Settings.yaml Neos: ContentRepository: Search: defaultConfigurationPerType: # strings should just be indexed with their simple value. string: elasticSearchMapping: type: string indexing: '${value}'
按属性索引配置
# NodeTypes.yaml 'Neos.Neos:Timable': properties: '_hiddenBeforeDateTime': search: # A date should be mapped differently, and in this case we want to use a date format which # Elasticsearch understands elasticSearchMapping: type: DateTime format: 'date_time_no_millis' indexing: '${(node.hiddenBeforeDateTime ? Date.format(node.hiddenBeforeDateTime, "Y-m-d\TH:i:sP") : null)}'
如果您的节点类型模式定义了DateTime类型的自定义属性,您必须在您的NodeTypes.yaml
中为它们提供类似的配置,否则它们将无法正确索引。
Indexing
命名空间中包含一些索引辅助工具,可以在indexing
表达式中使用。在大多数情况下,您不需要触摸此内容,但它们是构建标准索引配置所必需的。
Indexing.buildAllPathPrefixes
:对于如foo/bar/baz
这样的路径,构建路径前缀列表,例如['foo', 'foo/bar', 'foo/bar/baz']
。Indexing.extractNodeTypeNamesAndSupertypes(NodeType)
:提取传递的节点类型及其所有超类型节点类型名称的列表Indexing.convertArrayOfNodesToArrayOfNodeIdentifiers(array $nodes)
:将给定的节点转换为它们的节点标识符。
跳过属性的索引和映射
如果您不想属性被索引,请设置 indexing: false
。在这种情况下,此字段未配置映射。这也可以用来解决具有相同名称但类型不同的两个节点属性的类型冲突。
全文索引
为了启用全文索引,必须将每个 Document
节点配置为 全文根。因此,在默认配置中进行了以下配置
'Neos.Neos:Document': search: fulltext: isRoot: true
一个 全文根 包含其非文档子节点的所有 内容,这样当在这些文本中进行搜索时,文档本身会作为结果返回。
为了指定节点中属性的全文应如何提取,请在 NodeTypes.yaml
中的 properties.[propertyName].search.fulltextExtractor
进行配置。
示例
'Neos.Neos.NodeTypes:Text': properties: 'text': search: fulltextExtractor: '${Indexing.extractHtmlTags(value)}' 'My.Blog:Post': properties: title: search: fulltextExtractor: '${Indexing.extractInto("h1", value)}'
处理日期
默认情况下,Elasticsearch 在 UTC 时区中索引日期。为了使其使用当前配置的 PHP 时区进行索引,节点中代表日期的任何属性的配置应如下所示
'My.Blog:Post': properties: date: search: elasticSearchMapping: type: 'date' format: 'date_time_no_millis' indexing: '${(value ? Date.format(value, "Y-m-d\TH:i:sP") : null)}'
这对于基于日期和时间搜索按预期工作很重要,无论是使用格式化的 DateTime 字符串还是使用相对 DateTime 计算(例如:now
、now+1d
)。
如果您想按日期过滤项,例如显示日期晚于今天的项,您可以创建如下查询
${...greaterThan('date', Date.format(Date.Now(), "Y-m-d\TH:i:sP"))...}
有关 Elasticsearch 日期格式的更多信息,请点击此处。
处理资产/附件
如果您想索引附件,您需要安装Elasticsearch Ingest-Attachment 插件。然后,您可以将以下内容添加到您的 Settings.yaml
Neos: ContentRepository: Search: defaultConfigurationPerType: 'Neos\Media\Domain\Model\Asset': elasticSearchMapping: type: text indexing: ${Indexing.extractAssetContent(value)}
或将附件内容添加到 NodeType 配置中的全文字段
properties: file: type: 'Neos\Media\Domain\Model\Asset' ui: search: fulltextExtractor: ${Indexing.extractInto('text', Indexing.extractAssetContent(value))}
默认情况下,Indexing.extractAssetContent(value)
返回资产内容。您可以使用第二个参数返回资产元数据。字段参数可以设置为以下之一:content, title, name, author, keywords, date, content_type, content_length, language
。
有了这些,您可以将例如文件的标签添加到更高加权的字段中
properties: file: type: 'Neos\Media\Domain\Model\Asset' ui: search: fulltextExtractor: ${Indexing.extractInto('h2', Indexing.extractAssetContent(value, 'keywords'))}
查询数据
我们首先展示如何在 Fusion 中执行任意 Elasticsearch 查询。这是比 FlowQuery 更强大的替代方案。从长远来看,我们可能会将此 API 集成回 FlowQuery,但现在它按原样运行良好。
通常,使用 Search
Eel 辅助函数执行 Elasticsearch 查询。如果您想检索一个 节点列表,通常的做法是
nodes = ${Search.query(site)....execute()}
如果您只想检索一个 单个节点,查询的形式如下
nodes = ${q(Search.query(site)....execute()).get(0)}
要获取查询返回的命中总数,查询的形式如下
nodes = ${Search.query(site)....count()}
所有查询都在某个子节点下进行搜索。如果您想“全局”搜索,您将搜索当前站点节点(如上面的示例所示)。
此外,还支持以下运算符
作为 值,以下方法接受简单类型、节点对象或 DateTime 对象。
搜索结果高亮显示
使用 .fulltext()
或 .simpleQueryStringFulltext()
操作符进行全文搜索时,会自动查询 高亮片段(请参阅Elasticsearch 文档)。默认情况下,对所有可用的全文字段查询包含150个字符的片段,并使用150个字符的回退文本。
要调整此行为,您可以首先禁用默认设置,然后为每个字段单独配置高亮显示。
Search.highlight(false).highlight(150, 2, 150, 'neos_fulltext.text').highlight(100, 1, 0, 'neos_fulltext.h2')
这会禁用默认的高亮显示,然后从 neos_fulltext.text
中的命中结果查询2个150字符的片段,如果没有找到匹配项,则回退到文本的开头150个字符,并从 neos_fulltext.h2
中查询额外的100个字符,而不使用回退。
可以通过以下方式访问高亮片段:
highlight = ${Search(...).execute().searchHitForNode(node).highlight}
moreLikeThis(like, fields, options)
更多类似查询(MLT查询)可以找到与给定文本或给定文档集“类似”的文档。
like
单个值、字符串数组或节点数组。fields
用于比较其他文档与给定“类似”定义的字段数组。options
为more_like_this
查询提供的附加选项。请参阅Elasticsearch 文档以了解可用的选项。
低级操作
此外,还有一个更低级的操作符,可以用于添加任意的Elasticsearch过滤器。
queryFilter("filterType", {option1: "value1"}, [clauseType])
可选参数 clauseType
默认为 "must",可以用于指定布尔查询中的布尔运算符。它必须是 must
、should
、must_not
或 filter
之一。
在最低级别,有 request
操作符,允许以任意方式修改请求。请注意,如果传入的类型是数组,现有请求将与传入的类型合并。
request('query.filtered.query.bool.minimum_should_match', 1)
request('query.filtered.query.bool', {"minimum_should_match": 1})
为了更轻松地调试查询,以下操作很有帮助
log()
将执行时的完整查询记录到Elasticsearch日志中(即Data/Logs/ElasticSearch.log
)
示例查询
找到所有以特殊方式标记的页面并在概览中渲染它们
用例:在“标签概览”页面,您想显示以某种特定方式标记的所有页面
设置:您在一个名为 Acme.Blog:Post
和 Acme.Blog:Tag
的博客中拥有两种节点类型,它们都从 Neos.Neos:Document
继承。节点类型 Post
有一个属性 tags
,其类型为 references
,指向 Tag
文档。
融合设置
# for "Tag" documents, replace the main content area.
prototype(Neos.Neos:PrimaryContent).acmeBlogTag {
condition = ${q(node).is('[instanceof Acme.Blog:Tag]')}
type = 'Acme.Blog:TagPage'
}
# The "TagPage"
prototype(Acme.Blog:TagPage) < prototype(Neos.Fusion:Collection) {
collection = ${Search.query(site).nodeType('Acme.Blog:Post').exactMatch('tags', node).sortDesc('creationDate').execute()}
itemName = 'node'
itemRenderer = Acme.Blog:SingleTag
}
prototype(Acme.Blog:SingleTag) < prototype(Neos.Neos:Template) {
...
}
制作 OR 查询
此包中没有提供 OR 操作符,因此您需要使用自定义Elasticsearch查询过滤器来实现。
....queryFilter('bool', {should: [
{term: {tags: tagNode.identifier}},
{term: {places: tagNode.identifier}},
{term: {projects: tagNode.identifier}}
]})
聚合
聚合是轻松以不同方式聚合节点数据的一种方法。Elasticsearch提供了一些不同类型的聚合。有关聚合的更多信息,请参阅 https://elastic.ac.cn/guide/en/elasticsearch/reference/current/search-aggregations.html
。您可以使用它们来获取一些简单的聚合,如最小值、最大值或平均值等。聚合还可以允许您构建复杂的过滤器,例如产品搜索或统计。
聚合方法 目前已实现两种方法。一个通用的 aggregation
函数,允许您添加任何类型的聚合定义,以及一个预配置的 fieldBasedAggregation
。两种方法都可以添加到您的TS搜索查询中。您可以通过提供父名称来嵌套聚合。
aggregation($name, array $aggregationDefinition, $parentPath = NULL)
-- 在路径 $parentPath 下以名称 $name 添加 $aggregationDefinition 的通用方法。fieldBasedAggregation($name, $field, $type = 'terms', $parentPath = '', $size = 10)
-- 在路径 $parentPath 下添加一个简单字段基础聚合,类型为 $type,名称为 $name。用于简单的聚合,如求和、平均值、最小值、最大值或 terms。默认返回 10 个桶。
示例
聚合
添加一个平均聚合
要添加一个平均聚合,您可以使用 fieldBasedAggregation。此代码片段将为属性价格添加平均聚合
nodes = ${Search.query(site)...fieldBasedAggregation("avgprice", "price", "avg").execute()}
现在您可以使用以下方式在 fluid 模板中访问您的聚合
{nodes.aggregations}
创建嵌套聚合
在此场景中,您可以有一个表示产品的节点,该节点具有属性价格和颜色。如果您想了解所有颜色的平均价格,只需在 Fusion 中嵌套一个聚合即可
nodes = ${Search.query(site)...fieldBasedAggregation("colors", "color").fieldBasedAggregation("avgprice", "price", "avg", "colors").execute()}
第一个 fieldBasedAggregation
将添加一个简单的 terms 聚合(https://elastic.ac.cn/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html),名称为 colors。因此,您的 nodetype 的所有不同颜色都将列在这里。第二个 fieldBasedAggregation
将在您的 colors 聚合下添加另一个子聚合,名称为 avgprice。
您还可以像这样嵌套更多的聚合
fieldBasedAggregation("anotherAggregation", "field", "avg", "colors.avgprice")
添加自定义聚合
要添加自定义聚合,您可以使用 aggregation()
方法。您只需提供一个包含您的聚合定义的数组。此示例将执行与 fieldBasedAggregation 相同的操作
aggregationDefinition = Neos.Fusion:DataStructure {
terms = Neos.Fusion:DataStructure {
field = "color"
}
}
nodes = ${Search.query(site)...aggregation("color", this.aggregationDefinition).execute()}
产品过滤器
这是一个更复杂的场景。在此代码片段中,我们将创建一个基于所选节点的完整产品过滤器。想象一下一个 NodeTye ProductList,它有一个名为 products
的属性。此属性包含逗号分隔的 sku 列表。这也可能是其他产品的引用。
prototype(Vendor.Name:FilteredProductList) < prototype(Neos.Neos:Content)
prototype(Vendor.Name:FilteredProductList) {
// Create SearchFilter for products
searchFilter = Neos.Fusion:DataStructure {
sku = ${String.split(q(node).property("products"), ",")}
}
# Search for all products that matches your queryFilter and add aggregations
filter = ${Search.query(site).nodeType("Vendor.Name:Product").queryFilterMultiple(this.searchFilter, "must").fieldBasedAggregation("color", "color").fieldBasedAggregation("size", "size").execute()}
# Add more filter if get/post params are set
searchFilter.color = ${request.arguments.color}
searchFilter.color.@if.onlyRenderWhenFilterColorIsSet = ${request.arguments.color != ""}
searchFilter.size = ${request.arguments.size}
searchFilter.size.@if.onlyRenderWhenFilterSizeIsSet = ${request.arguments.size != ""}
# filter your products
products = ${Search.query(site).nodeType("Vendor.Name:Product").queryFilterMultiple(this.searchFilter, "must").execute()}
# don't cache this element
@cache {
mode = 'uncached'
context {
1 = 'node'
2 = 'site'
}
}
在前几行中,我们将添加一个新的 searchFilter 变量,并添加您选择的 sku 作为过滤器。基于此选择,我们将添加两个类型为 terms 的聚合。您可以在模板中使用 {filter.aggregations}
访问过滤器。有了这些信息,创建一个具有所有可用选项的表单就很容易了。如果您提交表单,请调用相同的页面并添加颜色和/或大小参数。下一行将解析这些参数并将它们添加到 searchFilter。基于您的选择,所有产品都将被检索并传递到您的模板。
重要提示
如果您使用 terms 过滤器,请注意 Elasticsearch 的字符串分析功能。您可能希望禁用所有可过滤属性的分析功能,否则过滤将无法正确执行。
'Vendor.Name:Product' properties: color: type: string defaultValue: '' search: elasticSearchMapping: type: keyword
排序
此包适配了 Elasticsearch 的排序功能。您可以在查询中添加多个排序操作。目前有三个您可以使用的方法
sortAsc('propertyName')
sortDesc('propertyName')
sort('configuration')
只需将这些方法附加到您的查询中,如下所示
# Sort ascending by property title
nodes = ${q(Search.query(site).....sortAsc("title").execute())}
# Sort for multiple properties
nodes = ${q(Search.query(site).....sortAsc("title").sortDesc("name").execute())}
# Custom sort operation
geoSorting = Neos.Fusion:DataStructure {
_geo_distance = Neos.Fusion:DataStructure {
latlng = Neos.Fusion:DataStructure {
lat = 51.512711
lon = 7.453084
}
order = "plane"
unit = "km"
distance_type = "sloppy_arc"
}
}
nodes = ${Search.query(site).....sort(this.geoSorting).execute()}
查看 https://elastic.ac.cn/guide/en/elasticsearch/reference/current/search-request-sort.html 了解更多配置选项。
带有分页和按距离排序的示例
这是一个更复杂的示例。想象一下,您想渲染一个节点列表,并且在每个节点旁边显示到特定点的距离。
首先,您必须在您的 NodeTypes.yaml 中为节点定义一个属性以存储 lat/lon 信息
'Vendor.Name:Retailer': properties: 'latlng': type: string search: elasticSearchMapping: type: "geo_point"
在 Fusion 中查询节点
geoSorting = Neos.Fusion:DataStructure {
_geo_distance {
geopoint {
lat = 51.512711
lon = 7.453084
}
order = "asc"
unit = "km"
ignore_unmapped = true
}
}
nodes = ${Search.query(site).nodeType('Vendor.Name:Retailer').sort(this.geoSorting)}
现在您可以在模板中分页这些节点。要获取每个节点的实际距离,请使用 GetHitArrayForNodeViewHelper
{namespace cr=Neos\ContentRepository\Search\ViewHelpers}
{namespace es=Flowpack\ElasticSearch\ContentRepositoryAdaptor\ViewHelpers}
<cr:widget.paginate query="{nodes}" as="paginatedNodes">
<f:for each="{paginatedNodes}" as="singleNode">
{singleNode.name} - <es:getHitArrayForNode queryResultObject="{nodes}" node="{singleNode}" path="sort.0" />
</f:for>
</cr:widget.paginate>
此 ViewHelper 将使用 \Neos\Utility\Arrays::getValueByPath() 返回指定的路径。因此,您可以使用数组或字符串。请参阅 \Neos\Utility\Arrays::getValueByPath() 的文档以获取更多信息。
重要提示
视图助手GetHitArrayForNode会返回原始命中结果数组。路径属性允许您访问一些特定数据,如排序数据。如果您的路径只有一个值,则将返回该值。如果有更多数据,GetHitArrayForNode-VH将返回完整的数组。因此,您可能需要使用ForViewHelper来访问您的排序值。
全文搜索/索引
在全文索引中搜索时,我们希望显示页面,或者更一般地说,显示所有是Document
节点的内容。然而,某个Document
的主要内容通常不存储在节点本身,而是存储在其(Content
)子节点中。
这就是为什么我们需要一些特殊的功能来进行索引,该功能将内部节点的内容添加到它们所属的Document
节点中,到一个名为neos_fulltext
和neos_fulltext_parts
的字段。
此外,我们希望全文匹配,例如在标题中,比在正常正文中的匹配更重要。这就是为什么Document
节点不仅包含一个包含所有文本的字段,还包含多个“桶”,文本被添加到其中:一个包含所有被认为“非常重要”的内容的字段(neos_fulltext.h1
),一个“不太重要”的字段(neos_fulltext.h2
),最后一个是纯文本(neos_fulltext.text
)。所有这些字段都配置了不同的boost
值。
有关搜索用户界面,请参阅Flowpack.SearchPlugin包
建议
Elasticsearch提供了一种简单的方法来根据您的查询获取查询建议。有关如何在您的搜索中构建和使用建议的更多信息,请参阅https://elastic.ac.cn/guide/en/elasticsearch/reference/current/search-suggesters.html
。
实现建议方法
已实现两种方法。suggestions
是一个通用的方法,允许您构建梦想中的建议查询。另一种方法是termSuggestions
,它旨在用于基本术语建议。它们可以被添加到您的令人惊叹的TS搜索查询中。
suggestions($name, array $suggestionDefinition)
-- 通用方法,用于填充自己的建议查询termSuggestions($term, $field = '_all', $name = 'suggestions')
-- 在所有字段上简单术语建议查询
示例
向查询添加简单建议
简单建议,基于发送的术语返回建议
suggestions = ${Search.query(site)...termSuggestions('someTerm')}
您可以使用以下方式在Fluid模板中访问您的建议
{nodes.suggestions}
添加自定义建议
短语查询,返回查询建议
suggestionsQueryDefinition = Neos.Fusion:DataStructure {
text = 'some Text'
simple_phrase = Neos.Fusion:DataStructure {
phrase = Neos.Fusion:DataStructure {
analyzer = 'body'
field = 'bigram'
size = 1
real_world_error_likelihood = 0.95
...
}
}
}
suggestions = ${Search.query(site)...suggestions('my_suggestions', this.suggestionsQueryDefinition)}
计算最大缓存时间
为了设置由Search()
获取的节点渲染的融合原型的最大缓存时间,需要计算所有节点在结果中的隐藏BeforeDateTime或hiddenAfterDateTime属性的最近未来值。
prototype(Acme.Blog:Listing) < prototype(Neos.Fusion:Collection) {
@context.searchQuery = ${Search.query(site).nodeType('Acme.Blog:Post')}
collection = ${searchQuery.execute()}
itemName = 'node'
itemRenderer = Acme.Blog:Post
@cache {
mode = 'cached'
maximumLifetime = ${searchQuery.cacheLifetime()}
entryTags {
map = ${'NodeType_Acme.Blog:Post'}
}
}
}
调试
为了理解发生了什么,以下内容可能会有所帮助
- 使用
./flow nodeindex:showMapping
来显示当前定义的Elasticsearch映射 - 在查询中使用
.log()
语句将它们转储到Elasticsearch日志 - 日志文件
Data/Logs/ElasticSearch.log
包含大量有用的信息。
Settings.yaml
- 将配置的基础命名空间从
Flowpack.ElasticSearch.ContentRepositoryAdaptor
更改为Neos.ContentRepository.Search
。所有进一步的调整都在此命名空间下进行。 - (如果您的配置中存在:将
indexName
移动到elasticSearch.indexName
) - (如果您的配置中存在:将
log
移动到elasticSearch.log
) - 搜索
mapping
(在defaultConfigurationPerType.<typeName>
内部),并用elasticSearchMapping
替换。 - 在
indexing
表达式(在defaultConfigurationPerType.<typeName>
内部),将ElasticSearch.
替换为Indexing.
。
NodeTypes.yaml
- 将
elasticSearch
替换为search
。这替换了<YourNodeType>.elasticSearch
和<YourNodeType>.properties.<propertyName>.elasticSearch
。 - 搜索
mapping
(在<YourNodeType>.properties.<propertyName>.search
内部),并用elasticSearchMapping
替换。 - 将
ElasticSeach.fulltext
替换为Indexing
。 - 在
indexing
表达式中搜索ElasticSearch.
并将其替换为Indexing.