传递的对象的弹性搜索数必须是偶数

时间:2016-08-28 00:55:27

标签: elasticsearch

我正在学习弹性搜索,我正在关注the next tutorial,但我收到了下一个错误

Exception in thread "main" java.lang.IllegalArgumentException: The number of object passed must be even but was [1]
at  org.elasticsearch.action.index.IndexRequest.source(IndexRequest.java:451)
at elastic.elasti.App.lambda$0(App.java:55)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at elastic.elasti.App.indexExampleData(App.java:53)
at elastic.elasti.App.main(App.java:45)

你能帮我解决一下吗?

public class App 
{
    public static void main( String[] args ) throws TwitterException, UnknownHostException
    {
    System.out.println( "Hello World!" );
    List tweetJsonList = searchForTweets();

    Client client = TransportClient.builder().build()
            .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
    String index = "tweets_juan";
    client.admin().indices()
                    .create(new CreateIndexRequest(index))
                    .actionGet();
    indexExampleData(client, tweetJsonList, index);
    searchExample(client);
}
public static void indexExampleData(Client client, List tweetJsonList, String index) {


    BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();

    tweetJsonList.forEach((jsonTweet) -> {
        bulkRequestBuilder.add(new IndexRequest(index, "tweets_juan")
                .source(jsonTweet));
    });

    BulkResponse bulkItemResponses = bulkRequestBuilder.get();
}




public static void searchExample(Client client) {
    BoolQueryBuilder queryBuilder = QueryBuilders
            .boolQuery()
            .must(termsQuery("text", "españa"));

    SearchResponse searchResponse = client.prepareSearch("tweets_juan")
            .setQuery(queryBuilder)
            .setSize(25)
            .execute()
            .actionGet();
     }

public static List searchForTweets() throws TwitterException {
    Twitter twitter = new TwitterFactory().getInstance();
    Query query = new Query("mundial baloncesto");
    List tweetList = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        QueryResult queryResult = twitter.search(query);
        tweetList.addAll(queryResult.getTweets());
        if (!queryResult.hasNext()) {
            break;
        }
        query = queryResult.nextQuery();
    }
    Gson gson = new Gson();

    return (List) tweetList.stream().map(gson::toJson).collect(Collectors.toList());
    }
}

4 个答案:

答案 0 :(得分:10)

我知道已经很晚了,但是对此的简单答案是添加XContentType.JSON以及在 ElasticSearch 库软件包org.elasticsearch.common.xcontent

中可用的源。
public static void indexExampleData(Client client, List tweetJsonList, String index) {


    BulkRequestBuilder bulkRequestBuilder = client.prepareBulk();

    tweetJsonList.forEach((jsonTweet) -> {
        bulkRequestBuilder.add(new IndexRequest(index, "tweets_juan")
                .source(jsonTweet,XContentType.JSON));
    });

    BulkResponse bulkItemResponses = bulkRequestBuilder.get();
}

答案 1 :(得分:7)

要点:

  1. Json对象不能用作索引的来源
  2. 使用像Jackson这样的东西对你的json进行Stringify或将源设置为Map
  3. 杰克逊:

    String stringifiedJson = objectMapper.writeValueAsString(jsonObject)

答案 2 :(得分:1)

如果您使用org.json库来管理JSON内容并遇到此错误,您可以通过这种方式解决此问题(将源设置为Map,如his answer中提出的skgemini):

JSONObject dataAsJson = new JSONObject(dataAsJsonFormattedString);
HashMap<String, Object> dataAsMap = new HashMap<String, Object>(dataAsJson.toMap());
bulkRequestBuilder.add(new IndexRequest(index, "tweets_juan").source(dataAsMap, XContentType.JSON));

答案 3 :(得分:0)

问题在于,弹性搜索不允许直接使用RequestIndexer API为JSON对象建立索引。因此,我们需要在XContentType.JSON方法中将source(sourceStr, XContentType.JSON)作为第二个参数传递。

使用以下组合进行了测试:

  • Elasticsearch版本:7.3.2
  • FlinkElasticConnector:flink-connector-elasticsearch7
  • Scala版本:2.13.1
  • Java版本:11.0.4

示例代码:

def sinkToES(counted: DataStream[(Employee, String)], index: String, indexType: String) = {
    try {
      val esSinkBuilder = new ElasticsearchSink.Builder[(Employee, String)](
        httpHosts, new ElasticsearchSinkFunction[(Employee, String)] {
          def process(element: (Employee, String), ctx: RuntimeContext, indexer: RequestIndexer) {
            val tenant = element._1.asInstanceOf[Employee].tenantId
            val sourceStr = JsonUtils.toJson[Employee](element._1.asInstanceOf[Employee])
            indexer.add(Requests.indexRequest.index(tenant + "_" + index).`type`(indexType).id(element._2).source(sourceStr, XContentType.JSON))
          }
        }
      )
      counted.addSink(esSinkBuilder.build())
    } catch {
      case e: Exception => logger.info("@@@@@@@Exception from this sinkDataToES method:-->" + e.printStackTrace)
    }
  }