首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将Scala对象序列化为Json并将其索引为Elasticsearch时,NotXContentException

将Scala对象序列化为Json并将其索引为Elasticsearch时,NotXContentException
EN

Stack Overflow用户
提问于 2016-02-22 22:13:59
回答 1查看 2K关注 0票数 2

我试图在Elasticsearch中索引一个相对复杂的Scala对象。以下是我的案例课:

代码语言:javascript
运行
复制
case class Game(id: Int,
            gameStates: Seq[GameState],
            playerActions: Map[String, PlayerAction],
            gameActions: Map[String, GameAction],
            endGame: EndGame)
case class GameState(players: Seq[Player])
case class Player(id: Int, deck: Seq[Card], playSpace: Seq[Card])
case class Card (rank: Int, suit: String) extends Ordered[Card]

对于这些案例类中的每一个,我都有一个伴生对象,该对象包含以这种样式编写的FormatObjectType写方法的定义:

代码语言:javascript
运行
复制
object Game {
  implicit object GameFormat extends Format[Game] {
    def writes(game: Game): JsValue = {
      Json.toJson(game.gameStates)
    }

    def reads(json:JsValue): JsResult[Game] = {
      //need this to satisfy compiler
      JsSuccess(Game(-1, Seq(), Map(), Map(), new EndGame("", (x: GameState) => None)))
    }
  }

  implicit object GameIndexable extends Indexable[Game] {
    override def json(game: Game): String =
      game.gameStates.map(x => Json.toJson(x).toString()).mkString(",")
  }
}

下面是执行索引的连接设置和方法:

代码语言:javascript
运行
复制
val settings = Settings.settingsBuilder()
                    .put("cluster.name", "elasticsearch_dan-dev").build()
val uri = ElasticsearchClientUri("elasticsearch://localhost:9300")
val esServer = ElasticClient.transport(settings, uri)

def sendGameToServer(game: Game) : Unit = {
  esServer.execute {
    index into "war" -> "games" source game
  }
}

当我运行我的应用程序时,当我尝试索引一个游戏对象时,我会从Elasticsearch中得到以下异常:

代码语言:javascript
运行
复制
[2016-02-22 13:34:28,247][DEBUG][action.index             ] [dan_01_dev] failed to execute [index {[war][games][AVMK56uUwAlQMxc6Khfa], source[_na_]}] on [[war][1]]
MapperParsingException[failed to parse]; nested: NotXContentException[Compressor detection can only be called on some xcontent bytes or compressed xcontent bytes];
    at org.elasticsearch.index.mapper.DocumentParser.innerParseDocument(DocumentParser.java:163)
    at org.elasticsearch.index.mapper.DocumentParser.parseDocument(DocumentParser.java:79)
    at org.elasticsearch.index.mapper.DocumentMapper.parse(DocumentMapper.java:304)
    at org.elasticsearch.index.shard.IndexShard.prepareCreate(IndexShard.java:500)
    at org.elasticsearch.index.shard.IndexShard.prepareCreateOnPrimary(IndexShard.java:481)
    at org.elasticsearch.action.index.TransportIndexAction.prepareIndexOperationOnPrimary(TransportIndexAction.java:214)
    at org.elasticsearch.action.index.TransportIndexAction.executeIndexRequestOnPrimary(TransportIndexAction.java:223)
    at org.elasticsearch.action.index.TransportIndexAction.shardOperationOnPrimary(TransportIndexAction.java:157)
    at org.elasticsearch.action.index.TransportIndexAction.shardOperationOnPrimary(TransportIndexAction.java:65)
    at org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryPhase.doRun(TransportReplicationAction.java:595)
    at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
    at org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryOperationTransportHandler.messageReceived(TransportReplicationAction.java:263)
    at org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryOperationTransportHandler.messageReceived(TransportReplicationAction.java:260)
    at org.elasticsearch.transport.TransportService$4.doRun(TransportService.java:350)
    at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.elasticsearch.common.compress.NotXContentException: Compressor detection can only be called on some xcontent bytes or compressed xcontent bytes
    at org.elasticsearch.common.compress.CompressorFactory.compressor(CompressorFactory.java:85)
    at org.elasticsearch.common.xcontent.XContentHelper.createParser(XContentHelper.java:50)
    at org.elasticsearch.index.mapper.DocumentParser.innerParseDocument(DocumentParser.java:99)
    ... 17 more

我很难找到关于这个例外的信息。我知道这意味着我的对象没有被正确的格式化为索引,但是我不知道如何排除这些问题。我已经确认,当我打印出Json而不是索引它时,我就有了有效的Json。对于为什么Elasticsearch不喜欢我试图索引的Json,有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-23 00:23:25

您的GameIndexable正在对映射的结果调用.mkString(","),因此您将得到一个"json“字符串,如下所示:

{ ... }, { ... }, { ... }

这是无效的Json。如果要索引多个游戏状态,则需要发出大量请求,每个请求都包含单个游戏状态。

或者,如果您希望索引Game对象,那么您的GameIndexable应该如下所示:

代码语言:javascript
运行
复制
implicit object GameIndexable extends Indexable[Game] {
  override def json(game: Game): String = GameFormat.writes(game).toString
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35564996

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档