elasticsearch - 根据数组 ElasticSearch 中的项目过滤文档
问题描述
我正在使用 ElasticSearch 搜索文档。但是,我需要确保当前用户能够看到这些文档。每个文档都与用户可能所属的社区相关联。
这是我的文档的映射:
export const mapping = {
properties: {
amazonId: { type: 'text' },
title: { type: 'text' },
subtitle: { type: 'text' },
description: { type: 'text' },
createdAt: { type: 'date' },
updatedAt: { type: 'date' },
published: { type: 'boolean' },
communities: { type: 'nested' }
}
}
我目前正在将文档所属社区的 ID 保存在字符串数组中。前任:["edd05cd0-0a49-4676-86f4-2db913235371", "672916cf-ee32-4bed-a60f-9a7c08dba04b"]
目前,当我使用 过滤查询时{term: { communities: community.id } }
,它会返回所有文档,而不管它与哪个社区相关联。
这是完整的查询:
{
index: 'document',
filter_path: { filter: {term: { communities: community.id } } },
body: {
sort: [{ createdAt: { order: 'asc' } }]
}
}
这是基于 的社区 id 得出的以下结果"b7d28e7f-7534-406a-981e-ddf147b5015a"
。注意:这是我的 graphql 的返回,因此文档上的社区在解决 ES 查询的命中后是实际的完整对象。
"hits": [
{
"title": "The One True Document",
"communities": [
{
"id": "edd05cd0-0a49-4676-86f4-2db913235371"
},
{
"id": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
}
]
},
{
"title": "Boring Document 1",
"communities": []
},
{
"title": "Boring Document 2",
"communities": []
},
{
"title": "Unpublished",
"communities": [
{
"id": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
}
]
}
]
当我{type: 'keyword', index: 'not_analyzed'}
收到一条错误消息时尝试绘制社区地图时,[illegal_argument_exception] Could not convert [communities.index] to boolean
.
那么我需要更改映射、过滤器还是两者都更改?在文档中搜索 6.6,我发现terms
需要non_analyzed
映射。
更新 - - - - - - - - - - - - -
我将社区映射更新keyword
为如下所示。但是,我仍然收到相同的结果。
我将查询更新为以下内容(使用包含文档的社区 ID):
query: { index: 'document',
body:
{ sort: [ { createdAt: { order: 'asc' } } ],
from: 0,
size: 5,
query:
{ bool:
{ filter:
{ term: { communities: '672916cf-ee32-4bed-a60f-9a7c08dba04b' } } } } } }
这给了我以下结果:
{
"data": {
"communities": [
{
"id": "672916cf-ee32-4bed-a60f-9a7c08dba04b",
"feed": {
"documents": {
"hits": []
}
}
}
]
}
}
看来我的过滤器工作得太好了?
解决方案
由于您正在存储社区的 id,因此您应该确保不会对这些 id 进行分析。因为这communities
应该是类型keyword
。其次,您要存储社区 ID 数组,因为用户可以属于多个社区。为此,您无需将其设为 type nested
。嵌套有不同的用例。要将值作为数组存储,您需要确保在索引时始终将值作为数组传递到字段中,即使该值是单个值。
您需要更改映射以及针对 field 索引值的方式communities
。
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"amazonId": {
"type": "text"
},
"title": {
"type": "text"
},
"subtitle": {
"type": "text"
},
"description": {
"type": "text"
},
"createdAt": {
"type": "date"
},
"updatedAt": {
"type": "date"
},
"published": {
"type": "boolean"
},
"communities": {
"type": "keyword"
}
}
}
}
}
2. 添加一个文档到索引:
PUT my_index/_doc/1
{
"title": "The One True Document",
"communities": [
"edd05cd0-0a49-4676-86f4-2db913235371",
"672916cf-ee32-4bed-a60f-9a7c08dba04b"
]
}
3.按社区ID过滤:
GET my_index/_doc/_search
{
"query": {
"bool": {
"filter": [
{
"term": {
"communities": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
}
}
]
}
}
}
嵌套字段方法
1. 映射:PUT my_index_2
{
"mappings": {
"_doc": {
"properties": {
"amazonId": {
"type": "text"
},
"title": {
"type": "text"
},
"subtitle": {
"type": "text"
},
"description": {
"type": "text"
},
"createdAt": {
"type": "date"
},
"updatedAt": {
"type": "date"
},
"published": {
"type": "boolean"
},
"communities": {
"type": "nested"
}
}
}
}
}
2. 索引文件:
PUT my_index_2/_doc/1
{
"title": "The One True Document",
"communities": [
{
"id": "edd05cd0-0a49-4676-86f4-2db913235371"
},
{
"id": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
}
]
}
3.查询(用于嵌套查询):
GET my_index_2/_doc/_search
{
"query": {
"bool": {
"filter": [
{
"nested": {
"path": "communities",
"query": {
"term": {
"communities.id.keyword": "672916cf-ee32-4bed-a60f-9a7c08dba04b"
}
}
}
}
]
}
}
}
你可能会注意到我用过communities.id.keyword
而不是communities.id
. 要了解其原因,请通过this。
推荐阅读
- php - 如何识别可用的 SOAP 函数?
- java - 在 Groovy 中编码时,“->” lamda 运算符有什么问题?
- python - 在日志中找到特定字符串时停止子进程
- javascript - REST API - CORS 问题
- nginx - Nginx - 如何创建将与 auth_request 模块一起使用的自定义请求
- java - 如何将 ArrayList 存储在文件中?
- python - 如何减小 5 层 for 循环的大小
- python - 考虑比例因子获取屏幕像素
- excel - “粘贴”运行时出现 VBA 运行时错误 438
- php - 如何从带有 ID PHP 的 XML 中获取数据