1

对于我正在处理的问题,我有大部分父/子文档解决方案,但我遇到了一个障碍:从迭代子文档的方面内部,我需要访问父文档字段的值。我有(或者我可以得到)父文档 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,但很想知道这是否有帮助。)

4

1 回答 1

0

鸣喇叭很好的免责声明:(1)我最终根本没有使用这种方法,所以这只是经过轻微测试的代码,以及(2)据我所知,它的效率非常低,并且它具有相同的内存开销父查询。如果另一种方法对您有用,请考虑它(对于我的用例,我最终使用了嵌套文档,并带有一个自定义的 facet 收集器,它遍历嵌套文档和父文档,以便轻松访问两者的字段值) .

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);

这使您可以在以下位置查找父文档的 UId doCollect(int childDocId)

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!");
        }
于 2013-09-05T09:27:11.700 回答