package mongoext import ( "testing" "git.blackforestbytes.com/BlackForestBytes/goext/tst" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" ) func TestFixTextSearchPipelineEmpty(t *testing.T) { pipeline := mongo.Pipeline{} result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 0) } func TestFixTextSearchPipelineNoTextSearch(t *testing.T) { pipeline := mongo.Pipeline{ bson.D{{Key: "$match", Value: bson.M{"foo": "bar"}}}, bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, } result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 2) tst.AssertEqual(t, result[0][0].Key, "$match") tst.AssertEqual(t, result[1][0].Key, "$sort") } func TestFixTextSearchPipelineMovesTextSearchToFront(t *testing.T) { pipeline := mongo.Pipeline{ bson.D{{Key: "$match", Value: bson.M{"foo": "bar"}}}, bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, bson.D{{Key: "$match", Value: bson.M{"$text": bson.M{"$search": "hello world"}}}}, } result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 3) // $text/$search should be at front first := result[0] matchVal, ok := first[0].Value.(bson.M) tst.AssertTrue(t, ok) textVal, ok := matchVal["$text"].(bson.M) tst.AssertTrue(t, ok) tst.AssertEqual(t, textVal["$search"].(string), "hello world") // other entries should preserve order tst.AssertEqual(t, result[1][0].Key, "$match") tst.AssertEqual(t, result[2][0].Key, "$sort") } func TestFixTextSearchPipelineMultipleTextSearches(t *testing.T) { pipeline := mongo.Pipeline{ bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, bson.D{{Key: "$match", Value: bson.M{"$text": bson.M{"$search": "first"}}}}, bson.D{{Key: "$match", Value: bson.M{"foo": "bar"}}}, bson.D{{Key: "$match", Value: bson.M{"$text": bson.M{"$search": "second"}}}}, } result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 4) // Last seen text-search should be prepended last, ending up at front. first := result[0][0].Value.(bson.M) tst.AssertEqual(t, first["$text"].(bson.M)["$search"].(string), "second") second := result[1][0].Value.(bson.M) tst.AssertEqual(t, second["$text"].(bson.M)["$search"].(string), "first") tst.AssertEqual(t, result[2][0].Key, "$sort") tst.AssertEqual(t, result[3][0].Key, "$match") } func TestFixTextSearchPipelineMatchWithoutText(t *testing.T) { pipeline := mongo.Pipeline{ bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, bson.D{{Key: "$match", Value: bson.M{"name": "alice"}}}, } result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 2) tst.AssertEqual(t, result[0][0].Key, "$sort") tst.AssertEqual(t, result[1][0].Key, "$match") } func TestFixTextSearchPipelineTextWithoutSearch(t *testing.T) { // $text present but without $search key — should NOT be moved pipeline := mongo.Pipeline{ bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, bson.D{{Key: "$match", Value: bson.M{"$text": bson.M{"$language": "en"}}}}, } result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 2) tst.AssertEqual(t, result[0][0].Key, "$sort") tst.AssertEqual(t, result[1][0].Key, "$match") } func TestFixTextSearchPipelineMatchValueWrongType(t *testing.T) { // $match with non-bson.M value — function should keep entry in place pipeline := mongo.Pipeline{ bson.D{{Key: "$match", Value: "not a map"}}, bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, } result := FixTextSearchPipeline(pipeline) tst.AssertEqual(t, len(result), 2) tst.AssertEqual(t, result[0][0].Key, "$match") tst.AssertEqual(t, result[1][0].Key, "$sort") } func TestFixTextSearchPipelinePreservesOriginal(t *testing.T) { original := mongo.Pipeline{ bson.D{{Key: "$sort", Value: bson.M{"baz": 1}}}, bson.D{{Key: "$match", Value: bson.M{"$text": bson.M{"$search": "x"}}}}, } originalLen := len(original) originalFirstKey := original[0][0].Key _ = FixTextSearchPipeline(original) tst.AssertEqual(t, len(original), originalLen) tst.AssertEqual(t, original[0][0].Key, originalFirstKey) }