RediSearch - NoContent option not working
alxgrk opened this issue · 3 comments
Hi there,
first, thanks for creating & maintaining this library.
I am using the redisearch module and tried to search for documents with NOCONTENT option set.
The following would be a sample request (in Kotlin):
myIndex.searchAsync("@foo:{bar}", SearchOptions().noContent())
However, for a result set of 1 document I get the following exception:
java.lang.IndexOutOfBoundsException: Index 2 out of bounds for length 2
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:459)
at io.github.dengliming.redismodule.redisearch.protocol.decoder.SearchResultDecoder.decode(SearchResultDecoder.java:58)
at io.github.dengliming.redismodule.redisearch.protocol.decoder.SearchResultDecoder.decode(SearchResultDecoder.java:31)
at org.redisson.client.protocol.decoder.ListMultiDecoder2.decode(ListMultiDecoder2.java:47)
at org.redisson.client.handler.CommandDecoder.decodeList(CommandDecoder.java:436)
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:392)
at org.redisson.client.handler.CommandDecoder.decodeCommand(CommandDecoder.java:198)
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:137)
at org.redisson.client.handler.CommandDecoder.decode(CommandDecoder.java:113)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:510)
at io.netty.handler.codec.ReplayingDecoder.callDecode(ReplayingDecoder.java:366)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:279)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
It seems that the logic at SearchResultDecoder
for whether noContent
was set or not is incorrect. At least, for the case where total == parts.get(0) == 1
, parts.size() + 1
would equal 3
, as parts.get(1)
is the id of the document.
@Override
public SearchResult decode(List<Object> parts, State state) {
Long total = (Long) parts.get(0);
int documentSize = withScores ? 3 : 2;
boolean noContent = total == parts.size() + 1;
List<Document> documents = new ArrayList<>(total.intValue());
// Checks the document size. DocumentSize equals to 2 means only key and parts. DocumentSize equals to 3 means
// key, score and parts. Created separated IFs to avoid checking this logic each document. Also changed the
// step size to reduce numbers of interactions
if (documentSize == 2) {
//Only key and parts
for (int i = 1; i < parts.size(); i += documentSize) {
if (noContent) {
documents.add(new Document((String) parts.get(i), 1.0d, null));
} else {
documents.add(new Document((String) parts.get(i), 1.0d, (Map<String, Object>) parts.get(i + 1)));
}
}
} else {
// ...
I'm not sure though how to fix this, any ideas? Just removing the + 1
part would surely do the trick, but does is still work with other result / document sizes?
Best regards,
Alex
@alxgrk Hey thanks for reporting this issue. I think this is a bug. Would you be interested in fixing it?
Here's a quick solution.
boolean noContent = total.longValue() == parts.size() - 1;
Fixed by cfe6e70
@dengliming thank you for fixing it so quickly. Whenever you find the time to create a new patch version, I would be happy to test the change.