From a93a2321f600379616837080452c192e23ed66c3 Mon Sep 17 00:00:00 2001 From: Kevin Hahn Date: Thu, 15 May 2025 14:13:26 +0700 Subject: [PATCH 1/2] tweak the example sentence filters so they match any sense, rather than requiring all senses to have no examples --- .../LexEntryFilterMapProvider.cs | 2 +- .../FwLite/LcmCrdt/EntryFilterMapProvider.cs | 2 +- .../MiniLcm.Tests/QueryEntryTestsBase.cs | 27 ++++++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/backend/FwLite/FwDataMiniLcmBridge/LexEntryFilterMapProvider.cs b/backend/FwLite/FwDataMiniLcmBridge/LexEntryFilterMapProvider.cs index b52d50de46..e96025705c 100644 --- a/backend/FwLite/FwDataMiniLcmBridge/LexEntryFilterMapProvider.cs +++ b/backend/FwLite/FwDataMiniLcmBridge/LexEntryFilterMapProvider.cs @@ -17,7 +17,7 @@ public class LexEntryFilterMapProvider : EntryFilterMapProvider // ReSharper disable once ConvertClosureToMethodGroup .Select(domain => LcmHelpers.GetSemanticDomainCode(domain)); public override Func? EntrySensesSemanticDomainsConverter => EntryFilter.NormalizeEmptyToNullString; - public override Expression> EntrySensesExampleSentences => e => EmptyToNull(e.AllSenses.SelectMany(s => s.ExamplesOS)); + public override Expression> EntrySensesExampleSentences => e => e.AllSenses.Select(s => EmptyToNull(s.ExamplesOS)); public override Expression> EntrySensesExampleSentencesSentence => (entry, ws) => entry.AllSenses.SelectMany(s => s.ExamplesOS).Select(example => example.PickText(example.Example, ws)); diff --git a/backend/FwLite/LcmCrdt/EntryFilterMapProvider.cs b/backend/FwLite/LcmCrdt/EntryFilterMapProvider.cs index a862a64bff..0d9a5d4e09 100644 --- a/backend/FwLite/LcmCrdt/EntryFilterMapProvider.cs +++ b/backend/FwLite/LcmCrdt/EntryFilterMapProvider.cs @@ -13,7 +13,7 @@ public class EntryFilterMapProvider : EntryFilterMapProvider public override Func? EntrySensesSemanticDomainsConverter => //linq2db treats Sense.SemanticDomains as a table, if we use "null" then it'll write the query we want EntryFilter.NormalizeEmptyToNullString; - public override Expression> EntrySensesExampleSentences => e => e.Senses.SelectMany(s => s.ExampleSentences); + public override Expression> EntrySensesExampleSentences => e => e.Senses.Select(s => s.ExampleSentences); public override Expression> EntrySensesExampleSentencesSentence => (e, ws) => e.Senses.SelectMany(s => s.ExampleSentences).Select(example => Json.Value(example.Sentence, ms => ms[ws])); public override Expression> EntrySensesPartOfSpeechId => e => e.Senses.Select(s => s.PartOfSpeechId); diff --git a/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs b/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs index 2ad35320c1..d6c3056319 100644 --- a/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs +++ b/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs @@ -5,6 +5,7 @@ public abstract class QueryEntryTestsBase : MiniLcmTestBase private readonly string Apple = "Apple"; private readonly string Peach = "Peach"; private readonly string Banana = "Banana"; + private readonly string Kiwi = "Kiwi"; public override async Task InitializeAsync() { @@ -59,6 +60,27 @@ await Api.CreateEntry(new Entry() } ] }); + await Api.CreateEntry(new Entry() + { + LexemeForm = { { "en", Kiwi } }, + Senses = + [ + new() + { + Gloss = { { "en", "Fruit" } }, + Definition = { { "en", "Fruit, fuzzy with green flesh" } }, + PartOfSpeechId = nounPos.Id, + SemanticDomains = [semanticDomain], + ExampleSentences = + [ + new ExampleSentence() + { + Sentence = { { "en", "I like eating Kiwis, they taste good" } } + }, + ] + } + ] + }); } [Fact] @@ -72,6 +94,7 @@ public async Task CanFilterToMissingSenses() public async Task CanFilterToMissingPartOfSpeech() { var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "Senses.PartOfSpeechId=null" })).ToArrayAsync(); + //does not include entries with no senses results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Peach); } @@ -79,7 +102,9 @@ public async Task CanFilterToMissingPartOfSpeech() public async Task CanFilterToMissingExamples() { var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "Senses.ExampleSentences=null" })).ToArrayAsync(); - results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo([Apple, Peach]); + //Senses.ExampleSentences=null matches entries which have senses but no examples + //it does not include Apple because it has no senses, to include it a filter Senses=null is needed + results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Peach, Banana); } [Fact] From bf6f07175400c4aaf0084ead6cd508d1a5df026d Mon Sep 17 00:00:00 2001 From: Kevin Hahn Date: Thu, 15 May 2025 14:24:48 +0700 Subject: [PATCH 2/2] fix some failing tests, add a test for entries that have senses --- .../FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs b/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs index d6c3056319..38a37f652a 100644 --- a/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs +++ b/backend/FwLite/MiniLcm.Tests/QueryEntryTestsBase.cs @@ -90,6 +90,13 @@ public async Task CanFilterToMissingSenses() results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Apple); } + [Fact] + public async Task CanFilterToNotMissingSenses() + { + var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "Senses!=null" })).ToArrayAsync(); + results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Kiwi, Peach, Banana); + } + [Fact] public async Task CanFilterToMissingPartOfSpeech() { @@ -125,21 +132,21 @@ public async Task CanFilterToMissingSemanticDomainsWithEmptyArray() public async Task CanFilterSemanticDomainCodeContains() { var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "Senses.SemanticDomains.Code=*Fruit" })).ToArrayAsync(); - results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Banana); + results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Banana, Kiwi); } [Fact] public async Task CanFilterToMissingComplexFormTypes() { var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "ComplexFormTypes=null" })).ToArrayAsync(); - results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Apple, Banana); + results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Apple, Banana, Kiwi); } [Fact] public async Task CanFilterToMissingComplexFormTypesWithEmptyArray() { var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "ComplexFormTypes=[]" })).ToArrayAsync(); - results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Apple, Banana); + results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Apple, Banana, Kiwi); } [Fact] @@ -188,7 +195,7 @@ public async Task CanFilterGlossEmpty() public async Task CanFilterGlossEqualsFruit() { var results = await Api.GetEntries(new(Filter: new() { GridifyFilter = "Senses.Gloss[en]=Fruit" })).ToArrayAsync(); - results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Banana); + results.Select(e => e.LexemeForm["en"]).Should().BeEquivalentTo(Banana, Kiwi); } [Fact]