elasticsearch-net
elasticsearch-net copied to clipboard
Adding an additional should-clause leads to no result
NEST/Elasticsearch.Net version: 7.15.0
Elasticsearch version: 7.15.1
.NET runtime version: net5.0
Operating system version: Windows 10
Description of the problem including expected versus actual behavior: In my application sometimes no result is found when there is a match. I was able to reproduce this with a simple test. I found out that when I add another should-clause on an empty field there is no match. In production it was a similar case but I'm not sure if this is the same one. We will see when this one is closed.
Steps to reproduce: Execute the following test. One test is OK the other one is failing:
public class TestElasticBugAdditionalShould
{
[Fact]
public async Task TestOk()
{
var indexName = $"{ Guid.NewGuid()}";
var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(connectionPool)
.DefaultMappingFor<ElasticTestIndexEntry>(m => m
.IndexName(indexName)
)
.EnableDebugMode()
.ThrowExceptions()
;
var client = new ElasticClient(connectionSettings);
try
{
await client.Indices.CreateAsync(indexName, c => c
.Map<ElasticTestIndexEntry>(m => m
.AutoMap()
// I'm not sure if this is necessary.
//.Properties(p => p
// .Text(t => t
// .Name(n => n.LabelGerman)
// .IndexPhrases()
// .IndexPrefixes(pp => pp)
// )
//)
)
);
var entries = new[]
{
new ElasticTestIndexEntry()
{
LabelGerman = "Zahlerplatz",
},
};
var bulkEntry = new BulkDescriptor();
bulkEntry.Refresh(Refresh.WaitFor);
foreach (var entry in entries)
bulkEntry.Index<ElasticTestIndexEntry>(i => i.Document(entry));
var bulkResponse = await client.BulkAsync(bulkEntry);
bulkResponse.ItemsWithErrors.Should().BeEmpty();
var result = await client.SearchAsync<ElasticTestIndexEntry>(r => r
.Explain()
.Query(q => q
.Bool(b => b
.Should(s => s
.MatchPhrasePrefix(p => p
.Field(f => f.LabelGerman)
.Query("Zahler")
)
)
// In the failed test this is active
//.Should(s => s
// .Field(f => f.DescriptionGerman)
// .Query("Zahler")
// )
//)
)
)
);
result.Total.Should().Be(1);
}
finally
{
await client.Indices.DeleteAsync(indexName);
}
}
[Fact]
public async Task TestNOk()
{
var indexName = $"{ Guid.NewGuid()}";
var connectionPool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var connectionSettings = new ConnectionSettings(connectionPool)
.DefaultMappingFor<ElasticTestIndexEntry>(m => m
.IndexName(indexName)
)
.EnableDebugMode()
.ThrowExceptions()
;
var client = new ElasticClient(connectionSettings);
try
{
await client.Indices.CreateAsync(indexName, c => c
.Map<ElasticTestIndexEntry>(m => m
.AutoMap()
// I'm not sure if this is necessary.
//.Properties(p => p
// .Text(t => t
// .Name(n => n.LabelGerman)
// .IndexPhrases()
// .IndexPrefixes(pp => pp)
// )
//)
)
);
var entries = new[]
{
new ElasticTestIndexEntry()
{
LabelGerman = "Zahlerplatz",
},
};
var bulkEntry = new BulkDescriptor();
bulkEntry.Refresh(Refresh.WaitFor);
foreach (var entry in entries)
bulkEntry.Index<ElasticTestIndexEntry>(i => i.Document(entry));
var bulkResponse = await client.BulkAsync(bulkEntry);
bulkResponse.ItemsWithErrors.Should().BeEmpty();
var result = await client.SearchAsync<ElasticTestIndexEntry>(r => r
.Explain()
.Query(q => q
.Bool(b => b
.Should(s => s
.MatchPhrasePrefix(p => p
.Field(f => f.LabelGerman)
.Query("Zahler")
)
)
.Should(s => s
.MatchPhrasePrefix(p => p
.Field(f => f.DescriptionGerman)
.Query("Zahler")
)
)
)
)
);
result.Total.Should().Be(1);
}
finally
{
await client.Indices.DeleteAsync(indexName);
}
}
public class ElasticTestIndexEntry
{
public string LabelGerman { get; set; }
public string DescriptionGerman { get; set; }
}
}
Expected behavior Both of the tests should succeed.
Provide ConnectionSettings
(if relevant):
Provide DebugInformation
(if relevant):
btw: I'm not sure if this is a NEST problem or belongs to the server itself.
@MartinDemberger, I'm incredibly sorry! This issue got missed and never picked up.
The problem here is the two calls to Should
where the last overwrites the first. In this case, you want to pass the params Func<QueryContainerDescriptor<T>, QueryContainer>[] queries
into Should
to provide multiple clauses.
e.g.
var result = await client.SearchAsync<ElasticTestIndexEntry>(r => r
.Explain()
.Query(q => q
.Bool(b => b
.Should(
s => s
.MatchPhrasePrefix(p => p
.Field(f => f.LabelGerman)
.Query("Zahler")
),
s => s
.MatchPhrasePrefix(p => p
.Field(f => f.DescriptionGerman)
.Query("Zahler")
)
)
)
)
);
As this is quite old, I'll close this issue, but please let me know if this doesn't resolve your problem.