在 Mapping 里面,将 dynamic 参数设置成 strict 可以拒绝索引包含未知字段的文档。 此条 Tips 由 medcl 贡献。

【源码篇】elasticsearch 搜索模块之preference参数

jiangtao 发表了文章 • 4 个评论 • 14843 次浏览 • 2017-10-26 19:20 • 来自相关话题

一,preference简述

elasticsearch可以使用preference参数来指定分片查询的优先级,即我们可以通过该参数来控制搜索时的索引数据分片。

如不设置该参数:在所有有效的主分片以及副本间轮询。

具体可看下:OperationRouting.java类
public ShardIterator activeInitializingShardsRandomIt() {
return activeInitializingShardsIt(shuffler.nextSeed());
}
//自增,以实现shard间轮询操作
public int nextSeed() {
return seed.getAndIncrement();
}

public ShardIterator activeInitializingShardsIt(int seed) {
if (allInitializingShards.isEmpty()) {
return new PlainShardIterator(shardId, shuffler.shuffle(activeShards, seed));
}
ArrayList<ShardRouting> ordered = new ArrayList<>(activeShards.size() + allInitializingShards.size());
ordered.addAll(shuffler.shuffle(activeShards, seed));
ordered.addAll(allInitializingShards);
return new PlainShardIterator(shardId, ordered);
}
 private ShardIterator preferenceActiveShardIterator(IndexShardRoutingTable indexShard, String localNodeId, DiscoveryNodes nodes, @Nullable String preference) {
        if (preference == null || preference.isEmpty()) {
            if (awarenessAttributes.length == 0) {
                return indexShard.activeInitializingShardsRandomIt();
            } else {
                return indexShard.preferAttributesActiveInitializingShardsIt(awarenessAttributes, nodes);
            }
        }
        if (preference.charAt(0) == '_') {
            Preference preferenceType = Preference.parse(preference);
            if (preferenceType == Preference.SHARDS) {
                // starts with _shards, so execute on specific ones
                int index = preference.indexOf('|');

                String shards;
                if (index == -1) {
                    shards = preference.substring(Preference.SHARDS.type().length() + 1);
                } else {
                    shards = preference.substring(Preference.SHARDS.type().length() + 1, index);
                }
                String ids = Strings.splitStringByCommaToArray(shards);
                boolean found = false;
                for (String id : ids) {
                    if (Integer.parseInt(id) == indexShard.shardId().id()) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    return null;
                }
                // no more preference
                if (index == -1 || index == preference.length() - 1) {
                    if (awarenessAttributes.length == 0) {
                        return indexShard.activeInitializingShardsRandomIt();
                    } else {
                        return indexShard.preferAttributesActiveInitializingShardsIt(awarenessAttributes, nodes);
                    }
                } else {
                    // update the preference and continue
                    preference = preference.substring(index + 1);
                }
            }
            preferenceType = Preference.parse(preference);
            switch (preferenceType) {
                case PREFER_NODES:
                    final Set<String> nodesIds =
                            Arrays.stream(
                                    preference.substring(Preference.PREFER_NODES.type().length() + 1).split(",")
                            ).collect(Collectors.toSet());
                    return indexShard.preferNodeActiveInitializingShardsIt(nodesIds);
                case LOCAL:
                    return indexShard.preferNodeActiveInitializingShardsIt(Collections.singleton(localNodeId));
                case PRIMARY:
                    return indexShard.primaryActiveInitializingShardIt();
                case REPLICA:
                    return indexShard.replicaActiveInitializingShardIt();
                case PRIMARY_FIRST:
                    return indexShard.primaryFirstActiveInitializingShardsIt();
                case REPLICA_FIRST:
                    return indexShard.replicaFirstActiveInitializingShardsIt();
                case ONLY_LOCAL:
                    return indexShard.onlyNodeActiveInitializingShardsIt(localNodeId);
                case ONLY_NODES:
                    String nodeAttributes = preference.substring(Preference.ONLY_NODES.type().length() + 1);
                    return indexShard.onlyNodeSelectorActiveInitializingShardsIt(nodeAttributes.split(","), nodes);
                default:
                    throw new IllegalArgumentException("unknown preference [" + preferenceType + "]");
            }
        }
        // if not, then use it as the index
        if (awarenessAttributes.length == 0) {
            return indexShard.activeInitializingShardsIt(Murmur3HashFunction.hash(preference));
        } else {
            return indexShard.preferAttributesActiveInitializingShardsIt(awarenessAttributes, nodes, Murmur3HashFunction.hash(preference));
        }
    }

 
 
二,结果震荡问题(Bouncing Results)
 
搜索同一query,结果ES返回的顺序却不尽相同,这就是请求轮询到不同分片,而未设置排序条件,相同相关性评分情况下,是按照所在segment中​lucene id来排序的,相同数据的不同备份之间该id是不能保证一致的,故造成结果震荡问题。
如设置该参数,则有一下9种情况

`_primary`:发送到集群的相关操作请求只会在主分片上执行。
`_primary_first`:指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。 
`_replica`:发送到集群的相关操作请求只会在副本上执行。
`_replica_first`:指查询会先在副本中查询,如果副本找不到(挂了),就会在主分片中查询。
`_local`: 指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。
`_prefer_nodes:abc,xyz`:在提供的节点上优先执行(在这种情况下为'abc'或'xyz')
`_shards:2,3`:限制操作到指定的分片。 (`2`和“3”)。这个偏好可以与其他偏好组合,但必须首先出现:`_shards:2,3 | _primary`
`_only_nodes:node1,node2`:指在指定id的节点里面进行查询,如果该节点只有要查询索引的部分分片,就只在这部分分片中查找,不同节点之间用“,”分隔。

custom(自定义):注意自定义的preference参数不能以下划线"_"开头。
当preference为自定义时,即该参数不为空,且开头不以“下划线”开头时,特别注意:如果以用户query作为自定义preference时,一定要处理以下划线开头的情况,这种情况下如果不属于以上8种情况,则会抛出异常。


三,参考:

https://www.elastic.co/guide/e ... .html
 

频繁删除数据

kennywu76 回复了问题 • 4 人关注 • 1 个回复 • 3695 次浏览 • 2017-10-26 17:39 • 来自相关话题

ElasticSearch数据时存储在内存中还是磁盘中

kennywu76 回复了问题 • 3 人关注 • 1 个回复 • 14663 次浏览 • 2017-10-26 17:46 • 来自相关话题

spring集成elasticsearch项目启动报错,求大神解惑

回复

Jayrun 发起了问题 • 1 人关注 • 0 个回复 • 3697 次浏览 • 2017-10-26 14:57 • 来自相关话题

关于elasticsearch重评分疑惑

回复

匿名用户 发起了问题 • 1 人关注 • 0 个回复 • 2159 次浏览 • 2017-10-26 13:30 • 来自相关话题

elastic对nested的数组对象排序

回复

jack 发起了问题 • 1 人关注 • 0 个回复 • 2862 次浏览 • 2017-10-26 09:11 • 来自相关话题

ES5.x版本下,suggestion 的java API问题

回复

xiaobingy 发起了问题 • 1 人关注 • 0 个回复 • 2876 次浏览 • 2017-10-25 15:10 • 来自相关话题

2.4版本分页查询速度很慢,如何优化。

skptopsec 回复了问题 • 3 人关注 • 4 个回复 • 3098 次浏览 • 2017-10-26 10:20 • 来自相关话题

elasticsearch head安装错误,http://localhost:9200/_plugin/head/访问error

laoyang360 回复了问题 • 4 人关注 • 3 个回复 • 14384 次浏览 • 2017-10-26 07:16 • 来自相关话题

elasticsearch关闭历史索引??

BrickXu 回复了问题 • 2 人关注 • 1 个回复 • 11258 次浏览 • 2017-10-25 12:14 • 来自相关话题

elasticsearch5.50 无法使用java bulk插入数据

回复

elasticsearch9 回复了问题 • 1 人关注 • 1 个回复 • 2541 次浏览 • 2017-11-06 14:46 • 来自相关话题

es删除索引超时

ELKer 回复了问题 • 6 人关注 • 2 个回复 • 11474 次浏览 • 2017-10-24 17:37 • 来自相关话题

elasticsearch垮机房的两个集群 如何保持数据一致性呢

回复

abc707 发起了问题 • 3 人关注 • 0 个回复 • 3609 次浏览 • 2017-10-24 15:43 • 来自相关话题

ik分词 maxword的slop

Wen Tan 回复了问题 • 4 人关注 • 2 个回复 • 3280 次浏览 • 2017-11-07 10:14 • 来自相关话题

es中primary_first参数可以配置在配置文件中吗?

回复

fairyland 发起了问题 • 1 人关注 • 0 个回复 • 3805 次浏览 • 2017-10-24 10:28 • 来自相关话题