medienreaktor / meilisearch
将 Meilisearch 集成到 Neos。
Requires
- guzzlehttp/guzzle: *
- http-interop/http-factory-guzzle: ^1.0
- meilisearch/meilisearch-php: *
- neos/content-repository: ^7.0 || ^8.0 || dev-master
- neos/content-repository-search: ^4.0 || dev-master
- neos/flow: ^7.0 || ^8.0 || dev-master
- neos/neos: ^7.0 || ^8.0 || dev-master
README
将 Meilisearch 集成到 Neos。 兼容 Meilisearch 版本 1.2 至 1.8 的测试。
此包旨在简洁和最小化依赖。因此,它可能不如像 Flowpack.ElasticSearch.ContentRepositoryAdaptor 这样的包复杂和可扩展,为了实现这一点,必须从这些优秀的包中复制一些代码部分(见致谢)。
✨ 特点
- ✅ 在 Meilisearch 中索引 Neos 内容库
- ✅ 支持所有节点变体的内容维度
- ✅ 命令行界面命令用于构建和刷新索引
- ✅ 通过搜索/ Eel 辅助程序和 QueryBuilder 查询索引
- ✅ 前端搜索表单、结果渲染和分页
- ✅ 分面和片段高亮显示
- ✅ 地理搜索过滤和排序
- ✅ 向量搜索用于语义搜索/人工智能搜索
- 🔴 目前尚不支持资产索引
- 🔴 不支持自动完成/自动建议(目前 Meilisearch 不支持此功能)
🚀 安装
通过 composer 安装
composer require medienreaktor/meilisearch
安装 Meilisearch 的开发方式有多种。如果你使用 DDEV,有一个 Meilisearch 片段。
⚙️ 配置
在你的 Settings.yaml
中配置 Meilisearch 客户端并设置端点和 API 密钥
Medienreaktor: Meilisearch: client: endpoint: '' apiKey: ''
你可以调整所有 Meilisearch 索引设置以满足你的需求(见 Meilisearch 文档)。这里配置的所有设置将直接传递给 Meilisearch。
Medienreaktor: Meilisearch: settings: displayedAttributes: - '*' searchableAttributes: - '__fulltext.text' - '__fulltext.h1' - '__fulltext.h2' - '__fulltext.h3' - '__fulltext.h4' - '__fulltext.h5' - '__fulltext.h6' filterableAttributes: - '__identifier' - '__dimensionsHash' - '__path' - '__parentPath' - '__nodeType' - '__nodeTypeAndSupertypes' - '_hidden' - '_hiddenBeforeDateTime' - '_hiddenAfterDateTime' - '_hiddenInIndex' - '_geo' sortableAttributes: - '_geo' rankingRules: - 'words' - 'typo' - 'proximity' - 'attribute' - 'sort' - 'exactness' stopWords: [] typoTolerance: enabled: true minWordSizeForTypos: oneTypo: 5 twoTypos: 9 faceting: maxValuesPerFacet: 100
请勿删除,只需扩展上述 filterableAttributes
,因为它们对于基本功能的工作是必需的。完成或更改配置后,请通过 CLI 命令 flow nodeindex:build
一次构建节点索引。
文档节点类型应配置为全文根(这是所有 Neos.Neos:Document
子类型的默认设置)
'Neos.Neos:Document': search: fulltext: isRoot: true enable: true
应适当配置应包含在全文搜索中的内容节点类型属性
'Neos.NodeTypes:Text': search: fulltext: enable: true properties: 'text': search: fulltextExtractor: "${Indexing.extractHtmlTags(node.properties.text)}" 'Neos.NodeTypes:Headline': search: fulltext: enable: true properties: 'title': search: fulltextExtractor: "${Indexing.extractHtmlTags(node.properties.title)}"
你会注意到一些属性被索引了两次,例如 _path
和 __path
,_nodeType
和 __nodeType
。这是由于这些节点属性的不同 隐私
_*
-属性是默认的 Neos 节点属性,对 Neos 是私有的(并且可能更改)__*
-属性是私有属性,对于 Meilisearch 集成是必需的
我们必须确保我们所需的属性始终存在,因此最好单独索引它们。
📖 与 Neos 和 Fusion 一起使用
有一个内置的内容节点类型 Medienreaktor.Meilisearch:Search
用于渲染搜索表单、结果和分页,这可能作为你项目的样板。只需将其放置在搜索页面上即可开始。
你还可以在你的 Fusion 组件中使用搜索查询、结果和分面。
prototype(Medienreaktor.Meilisearch:Search) < prototype(Neos.Neos:ContentComponent) {
searchTerm = ${String.toString(request.arguments.search)}
page = ${String.toInteger(request.arguments.page) || 1}
hitsPerPage = 10
searchQuery = ${this.searchTerm ? Search.query(site).fulltext(this.searchTerm).nodeType('Neos.Neos:Document') : null}
searchQuery.@process {
page = ${value.page(this.page)}
hitsPerPage = ${value.hitsPerPage(this.hitsPerPage)}
}
facets = ${this.searchQuery.facets(['__nodeType', '__parentPath'])}
totalPages = ${this.searchQuery.totalPages()}
totalHits = ${this.searchQuery.totalHits()}
}
如果你想为某些节点属性提供分面分布或在其中进行搜索,请确保将它们添加到 Settings.yaml
中的 filterableAttributes
和/或 searchableAttributes
。
搜索查询构建器支持以下功能
⚡ 与 JavaScript / React / Vue 一起使用
如果您想使用JavaScript、React或Vue构建前端,您可以完全忽略上面的Neos和Fusion集成,并使用instant-meilisearch
。
请注意以下三件事
1. 节点上下文和维度的过滤
设置您的过滤器始终包含以下过滤器字符串:(__parentPath = "$nodePath" OR __path = "$nodePath") AND __dimensionsHash = "$dimensionsHash"
,其中$nodePath
是上下文节点的NodePath(例如网站),$dimensionsHash
是MD5散列的JSON编码上下文维度数组。
您可以在PHP中使用以下方式获取这些值
$nodePath = (string) $contextNode->findNodePath(); $dimensionsHash = md5(json_encode($contextNode->getContext()->getDimensions()));
在Fusion中,您可以通过以下方式获取这些值(假设site
是您希望使用的上下文节点)
nodePath = ${site.path}
dimensionsHash = ${String.md5(Json.stringify(site.context.dimensions))}
2. 节点URI
节点的公共URI位于每个Meilisearch结果命中项的__uri
属性中。
它在索引时生成,这也是为什么即使由于维度回退行为它们是冗余的,我们也会为每个节点变体创建单独的索引记录。这与Flowpack.ElasticSearch.ContentRepositoryAdaptor相反,其中只创建一个记录,并分配多个维度散列。
为了使URI生成正常工作,为您的每个站点分配一个主域名非常重要。
3. 图片URI
如果您需要在您的前端中使用图片URI,这也可以进行配置。首先,请确保在您的Settings.yaml
中设置一个基本URL
Neos:
Flow:
http:
baseUri: https://example.com/
然后,配置您的特定属性或所有图片属性以进行索引
Neos:
ContentRepository:
Search:
defaultConfigurationPerType:
Neos\Media\Domain\Model\ImageInterface:
indexing: '${AssetUri.build(value, 600, 400)}'
您可以在方法参数中设置您想要的width
、height
和可选的allowCropping
、allowUpScaling
和format
值。
📍 地理搜索
Meilisearch支持基于地理位置的过滤和排序。为此功能正常工作,您的节点应提供包含lat
/lng
值的__geo
属性。实现此功能的一种简单方法是使用代理属性
'Neos.Neos:Document':
properties:
latitude:
type: 'string'
ui:
label: 'Latitude'
longitude:
type: 'string'
ui:
label: 'Longitude'
__geo:
search:
indexing: "${{lat: node.properties.latitude, lng: node.properties.longitude}}"
搜索查询构建器支持使用geoRadius()
进行过滤和使用geoPoint()
进行排序(见上文)。
📐 向量搜索
您可以使用Meilisearch作为具有实验性向量搜索功能的向量存储。使用/experimental-features
端点激活它,如发布说明中所述。
每个文档的向量必须由您提供并在节点的_vector
属性中索引。这可以通过编写一个自定义Eel助手来实现,该助手使用第三方工具(如OpenAI或Hugging Face)计算向量。
'Neos.Neos:Document':
properties:
_vector:
search:
indexing: "${VectorIndexing.computeByNode(node)}"
搜索查询构建器支持通过向量进行查询。根据您的用例,必须在搜索短语中重新计算向量,例如
prototype(Medienreaktor.Meilisearch:Search) < prototype(Neos.Neos:ContentComponent) {
searchTerm = ${String.toString(request.arguments.search)}
searchVector = ${VectorIndexing.computeByString(this.searchTerm)}
vectorSearchQuery = ${this.searchVector ? Search.query(site).vector(this.searchVector) : null}
searchResults = ${this.vectorSearchQuery.execute()}
}
要显示与当前文档类似的文档(例如用于维基、知识库或新闻室),请使用当前文档的向量作为搜索向量。
👩💻 致谢
此软件包受到以下软件包的极大启发,并复制了一些较小的代码部分:
- Sandstorm.LightweightElasticsearch
- Flowpack.ElasticSearch.ContentRepositoryAdaptor
- Flowpack.SimpleSearch.ContentRepositoryAdaptor
- Flowpack.SearchPlugin
所有荣誉都归功于这些软件包的原始作者。