88using Foundatio . Repositories . Models ;
99using Newtonsoft . Json ;
1010using Xunit ;
11- using Xunit . Abstractions ;
1211
1312namespace Foundatio . Repositories . Elasticsearch . Tests ;
1413
@@ -21,7 +20,7 @@ public NestedFieldTests(ITestOutputHelper output) : base(output)
2120 _employeeRepository = new EmployeeRepository ( _configuration ) ;
2221 }
2322
24- public override async Task InitializeAsync ( )
23+ public override async ValueTask InitializeAsync ( )
2524 {
2625 await base . InitializeAsync ( ) ;
2726 await RemoveDataAsync ( ) ;
@@ -48,10 +47,9 @@ public async Task FindAsync_WithNestedPeerReviewOrCondition_ReturnsMatchingEmplo
4847 ] ;
4948
5049 await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
51- var searchRepository = ( ISearchableReadOnlyRepository < Employee > ) _employeeRepository ;
5250
5351 // Act
54- var results = await searchRepository . FindAsync ( q => q . FilterExpression ( "peerReviews.rating:>=4 OR peerReviews.reviewerEmployeeId:bob_456" ) ) ;
52+ var results = await _employeeRepository . FindAsync ( q => q . FilterExpression ( "peerReviews.rating:>=4 OR peerReviews.reviewerEmployeeId:bob_456" ) ) ;
5553
5654 // Assert
5755 Assert . Equal ( 2 , results . Documents . Count ) ;
@@ -90,7 +88,6 @@ public async Task CountAsync_WithNestedPeerReviewAggregation_ReturnsAggregationD
9088 // Assert
9189 Assert . Equal ( 3 , result . Total ) ;
9290 Assert . Single ( result . Aggregations ) ;
93- Assert . NotEmpty ( result . Aggregations ) ;
9491
9592 var nestedPeerReviewsAgg = result . Aggregations [ "nested_peerReviews" ] as SingleBucketAggregate ;
9693 Assert . NotNull ( nestedPeerReviewsAgg ) ;
@@ -119,10 +116,9 @@ public async Task FindAsync_WithNestedFieldInDefaultSearch_ReturnsMatchingEmploy
119116 ] ;
120117
121118 await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
122- var searchRepository = ( ISearchableReadOnlyRepository < Employee > ) _employeeRepository ;
123119
124120 // Act
125- var results = await searchRepository . FindAsync ( q => q . SearchExpression ( specialReviewerId ) ) ;
121+ var results = await _employeeRepository . FindAsync ( q => q . SearchExpression ( specialReviewerId ) ) ;
126122
127123 // Assert
128124 Assert . Single ( results . Documents ) ;
@@ -405,4 +401,152 @@ public async Task CountAsync_WithNestedAggregationsSerialization_CanRoundtripBot
405401 bucket = roundTrippedRatingTermsAgg . Buckets . First ( f => f . Key == 5 ) ;
406402 Assert . Equal ( 2 , bucket . Total ) ;
407403 }
404+
405+ [ Fact ]
406+ public async Task FindAsync_WithIndividualNestedFieldWithoutGroupSyntax_ReturnsMatchingEmployee ( )
407+ {
408+ // Arrange
409+ List < Employee > employees =
410+ [
411+ EmployeeGenerator . Generate ( "alice_123" , "Alice" , peerReviews :
412+ [
413+ new PeerReview { ReviewerEmployeeId = "bob_456" , Rating = 5 }
414+ ] ) ,
415+ EmployeeGenerator . Generate ( "bob_456" , "Bob" , peerReviews :
416+ [
417+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 3 }
418+ ] )
419+ ] ;
420+
421+ await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
422+
423+ // Act
424+ var results = await _employeeRepository . FindAsync ( q => q . FilterExpression ( "peerReviews.rating:5" ) ) ;
425+
426+ // Assert
427+ Assert . Single ( results . Documents ) ;
428+ Assert . Equal ( "Alice" , results . Documents . Single ( ) . Name ) ;
429+ }
430+
431+ [ Fact ]
432+ public async Task FindAsync_WithNestedRangeQuery_ReturnsMatchingEmployees ( )
433+ {
434+ // Arrange
435+ List < Employee > employees =
436+ [
437+ EmployeeGenerator . Generate ( "alice_123" , "Alice" , peerReviews :
438+ [
439+ new PeerReview { ReviewerEmployeeId = "bob_456" , Rating = 5 }
440+ ] ) ,
441+ EmployeeGenerator . Generate ( "bob_456" , "Bob" , peerReviews :
442+ [
443+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 2 }
444+ ] ) ,
445+ EmployeeGenerator . Generate ( "charlie_789" , "Charlie" , peerReviews :
446+ [
447+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 4 }
448+ ] )
449+ ] ;
450+
451+ await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
452+
453+ // Act
454+ var results = await _employeeRepository . FindAsync ( q => q . FilterExpression ( "peerReviews.rating:[4 TO 5]" ) ) ;
455+
456+ // Assert
457+ Assert . Equal ( 2 , results . Documents . Count ) ;
458+ Assert . Contains ( results . Documents , e => String . Equals ( e . Name , "Alice" ) ) ;
459+ Assert . Contains ( results . Documents , e => String . Equals ( e . Name , "Charlie" ) ) ;
460+ }
461+
462+ [ Fact ]
463+ public async Task FindAsync_WithNestedAndConditionWithoutGroupSyntax_ReturnsMatchingEmployee ( )
464+ {
465+ // Arrange
466+ List < Employee > employees =
467+ [
468+ EmployeeGenerator . Generate ( "alice_123" , "Alice" , peerReviews :
469+ [
470+ new PeerReview { ReviewerEmployeeId = "bob_456" , Rating = 5 }
471+ ] ) ,
472+ EmployeeGenerator . Generate ( "bob_456" , "Bob" , peerReviews :
473+ [
474+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 5 }
475+ ] ) ,
476+ EmployeeGenerator . Generate ( "charlie_789" , "Charlie" , peerReviews :
477+ [
478+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 3 }
479+ ] )
480+ ] ;
481+
482+ await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
483+
484+ // Act
485+ var results = await _employeeRepository . FindAsync ( q => q . FilterExpression ( "peerReviews.rating:5 AND peerReviews.reviewerEmployeeId:bob_456" ) ) ;
486+
487+ // Assert
488+ Assert . Single ( results . Documents ) ;
489+ Assert . Equal ( "Alice" , results . Documents . Single ( ) . Name ) ;
490+ }
491+
492+ [ Fact ]
493+ public async Task FindAsync_WithMixedNestedAndNonNestedFields_ReturnsMatchingEmployee ( )
494+ {
495+ // Arrange
496+ List < Employee > employees =
497+ [
498+ EmployeeGenerator . Generate ( "alice_123" , "Alice" , peerReviews :
499+ [
500+ new PeerReview { ReviewerEmployeeId = "bob_456" , Rating = 5 }
501+ ] ) ,
502+ EmployeeGenerator . Generate ( "bob_456" , "Bob" , peerReviews :
503+ [
504+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 5 }
505+ ] ) ,
506+ EmployeeGenerator . Generate ( "charlie_789" , "Charlie" , peerReviews :
507+ [
508+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 3 }
509+ ] )
510+ ] ;
511+
512+ await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
513+
514+ // Act
515+ var results = await _employeeRepository . FindAsync ( q => q . FilterExpression ( "name:Alice peerReviews.rating:5" ) ) ;
516+
517+ // Assert
518+ Assert . Single ( results . Documents ) ;
519+ Assert . Equal ( "Alice" , results . Documents . Single ( ) . Name ) ;
520+ }
521+
522+ [ Fact ]
523+ public async Task FindAsync_WithNegatedNestedGroup_ExcludesMatchingEmployees ( )
524+ {
525+ // Arrange
526+ List < Employee > employees =
527+ [
528+ EmployeeGenerator . Generate ( "alice_123" , "Alice" , peerReviews :
529+ [
530+ new PeerReview { ReviewerEmployeeId = "bob_456" , Rating = 5 }
531+ ] ) ,
532+ EmployeeGenerator . Generate ( "bob_456" , "Bob" , peerReviews :
533+ [
534+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 3 }
535+ ] ) ,
536+ EmployeeGenerator . Generate ( "charlie_789" , "Charlie" , peerReviews :
537+ [
538+ new PeerReview { ReviewerEmployeeId = "alice_123" , Rating = 4 }
539+ ] )
540+ ] ;
541+
542+ await _employeeRepository . AddAsync ( employees , o => o . ImmediateConsistency ( ) ) ;
543+
544+ // Act
545+ var results = await _employeeRepository . FindAsync ( q => q . FilterExpression ( "NOT peerReviews.rating:5" ) ) ;
546+
547+ // Assert
548+ Assert . Equal ( 2 , results . Documents . Count ) ;
549+ Assert . Contains ( results . Documents , e => String . Equals ( e . Name , "Bob" ) ) ;
550+ Assert . Contains ( results . Documents , e => String . Equals ( e . Name , "Charlie" ) ) ;
551+ }
408552}
0 commit comments