gpt4 book ai didi

java - 如何从子文档的自定义方面访问 ElasticSearch 父文档字段

转载 作者:行者123 更新时间:2023-12-01 04:26:05 25 4
gpt4 key购买 nike

对于我正在处理的问题,我有大部分父/子文档解决方案,但我遇到了麻烦:从迭代子文档的方面内部,我需要访问父文档的值 field 。我有(或者我可以获取)父文档 ID(来自子文档的 _parent 字段,或者最坏的情况是通过将其再次索引为普通字段),但这是一个“外部”ID,而不是我的节点内部 ID需要从字段缓存中加载字段值。 (我使用默认路由,因此父文档肯定与子文档位于同一个分片中。)

更具体地说,这是我迄今为止在 FacetCollector 中拥有的内容(ES 0.20.6):

protected void doSetNextReader(IndexReader reader, int docBase) throws IOException {
/* not sure this will work, otherwise I can index the field seperately */
parentFieldData = (LongFieldData) fieldDataCache.cache(FieldDataType.DefaultTypes.LONG, reader, "_parent");
parentSpringinessFieldData = (FloatFieldData) fieldDataCache.cache(FieldDataType.DefaultTypes.FLOAT, "springiness");
/* ... */

protected void doCollect(int doc) throws IOException {
long parentID = parentFieldData.value(doc); // or whatever the correct equivalent here is
// here's the problem:
parentSpringiness = parentSpringinessFieldData.value(parentID)
// type error: expected int (node-internal ID), got long (external ID)

有什么建议吗? (我还无法升级到 0.90,但我很想知道这是否有帮助。)

最佳答案

鸣响伟大的免责声明:(1)我最终根本没有使用这种方法,所以这只是经过轻微测试的代码,(2)据我所知,它将非常低效,并且它具有相同的作为父查询的内存开销。如果另一种方法适合您,请考虑它(对于我的用例,我最终使用嵌套文档,并使用自定义构面收集器来迭代嵌套文档和父文档,以便轻松访问两者的字段值) .

ES 代码中的示例是org.elasticsearch.index.search.child.ChildCollector。您需要的第一个元素位于收集器初始化中:

    try {
context.idCache().refresh(context.searcher().subReaders());
} catch (Exception e) {
throw new FacetPhaseExecutionException(facetName, "Failed to load parent-ID cache", e);
}

这使得 doSetNextReader() 中的以下行成为可能:

typeCache = context.idCache().reader(reader).type(parentType);

它可以让您在 doCollect(int childDocId) 中查找父文档的 UId:

HashedBytesArray postingUid = typeCache.parentIdByDoc(childDocId);

父文档不一定能在与子文档相同的读取器中找到:当收集器初始化时,您还需要存储所有读取器(需要访问字段值),并为每个读取器存储一个 IdReaderTypeCache (将父文档的 UId 解析为读者内部 docId)。

    this.readers = new Tuple[context.searcher().subReaders().length];
for (int i = 0; i < readers.length; i++) {
IndexReader reader = context.searcher().subReaders()[i];
readers[i] = new Tuple<IndexReader, IdReaderTypeCache>(reader, context.idCache().reader(reader).type(parentType));
}
this.context = context;

然后,当您需要父文档字段时,您必须迭代读取器/类型缓存对以查找正确的一个:

        int parentDocId = -1;
for (Tuple<IndexReader, IdReaderTypeCache> tuple : readers) {
IndexReader indexReader = tuple.v1();
IdReaderTypeCache idReaderTypeCache = tuple.v2();
if (idReaderTypeCache == null) { // might be if we don't have that doc with that type in this reader
continue;
}
parentDocId = idReaderTypeCache.docById(postingUid);
if (parentDocId != -1 && !indexReader.isDeleted(parentDocId)) {
FloatFieldData parentSpringinessFieldData = (FloatFieldData) fieldDataCache.cache(
FieldDataType.DefaultTypes.FLOAT,
indexReader,
"springiness");
parentSpringiness = parentSpringinessFieldData.value(parentDocId);
break;
}
}
if (parentDocId == -1) {
throw new FacetPhaseExecutionException(facetName, "Parent doc " + postingUid + " could not be found!");
}

关于java - 如何从子文档的自定义方面访问 ElasticSearch 父文档字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18481083/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com