Skip to content

Commit

Permalink
CSHARP-4938: Support for indexing and querying on UUID and null datat…
Browse files Browse the repository at this point in the history
…ype (#1563)
  • Loading branch information
papafe authored Dec 4, 2024
1 parent ee12544 commit de3adba
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 5 deletions.
3 changes: 3 additions & 0 deletions src/MongoDB.Driver/Search/OperatorSearchDefinitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ private static BsonValue ToBsonValue(TField value) =>
DateTime v => (BsonDateTime)v,
DateTimeOffset v => (BsonDateTime)v.UtcDateTime,
ObjectId v => (BsonObjectId)v,
Guid v => new BsonBinaryData(v, GuidRepresentation.Standard),
string v => (BsonString)v,
null => BsonNull.Value,
_ => throw new InvalidCastException()
};
}
Expand Down Expand Up @@ -259,6 +261,7 @@ private static BsonValue ToBsonValue(TField value) =>
DateTimeOffset v => (BsonDateTime)v.UtcDateTime,
string v => (BsonString)v,
ObjectId v => (BsonObjectId)v,
Guid v => new BsonBinaryData(v, GuidRepresentation.Standard),
_ => throw new InvalidCastException()
};
}
Expand Down
8 changes: 4 additions & 4 deletions src/MongoDB.Driver/Search/SearchDefinitionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public SearchDefinition<TDocument> EmbeddedDocument<TField>(
/// <summary>
/// Creates a search definition that queries for documents where an indexed field is equal
/// to the specified value.
/// Supported value types are boolean, numeric, ObjectId, date and string.
/// Supported value types are null, boolean, numeric, ObjectId, Guid, date and string.
/// </summary>
/// <typeparam name="TField">The type of the field.</typeparam>
/// <param name="path">The indexed field to search.</param>
Expand All @@ -127,7 +127,7 @@ public SearchDefinition<TDocument> Equals<TField>(
/// <summary>
/// Creates a search definition that queries for documents where an indexed field is equal
/// to the specified value.
/// Supported value types are boolean, numeric, ObjectId, date and string.
/// Supported value types are null, boolean, numeric, ObjectId, Guid, date and string.
/// </summary>
/// <typeparam name="TField">The type of the field.</typeparam>
/// <param name="path">The indexed field to search.</param>
Expand Down Expand Up @@ -316,7 +316,7 @@ public SearchDefinition<TDocument> GeoWithin<TCoordinates>(
/// <summary>
/// Creates a search definition that queries for documents where the value of the field equals to any of specified values.
/// </summary>
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, number, date, string.</typeparam>
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, Guid, number, date, string.</typeparam>
/// <param name="path">The indexed field or fields to search.</param>
/// <param name="values">Values to compare the field with.</param>
/// <param name="score">The score modifier.</param>
Expand All @@ -330,7 +330,7 @@ public SearchDefinition<TDocument> In<TField>(
/// <summary>
/// Creates a search definition that queries for documents where the value of the field equals to any of specified values.
/// </summary>
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, number, date, string.</typeparam>
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, Guid, number, date, string.</typeparam>
/// <param name="path">The indexed field or fields to search.</param>
/// <param name="values">Values to compare the field with.</param>
/// <param name="score">The score modifier.</param>
Expand Down
60 changes: 60 additions & 0 deletions tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,28 @@ public void EmbeddedDocument()
}
}

[Fact]
public void EqualsGuid()
{
var testGuid = Guid.Parse("b52af144-bc97-454f-a578-418a64fa95bf");

var result = GetExtraTestsCollection().Aggregate()
.Search(Builders<TestClass>.Search.Equals(c => c.TestGuid, testGuid))
.Single();

result.Name.Should().Be("test6");
}

[Fact]
public void EqualsNull()
{
var result = GetExtraTestsCollection().Aggregate()
.Search(Builders<TestClass>.Search.Equals(c => c.TestString, null))
.Single();

result.Name.Should().Be("testNull");
}

[Fact]
public void EqualsArrayField()
{
Expand Down Expand Up @@ -266,6 +288,23 @@ public void In()
results[1].Runtime.Should().Be(31);
}

[Fact]
public void InGuid()
{
var testGuids = new[]
{
Guid.Parse("b52af144-bc97-454f-a578-418a64fa95bf"), Guid.Parse("84da5d44-bc97-454f-a578-418a64fa937a")
};

var result = GetExtraTestsCollection().Aggregate()
.Search(Builders<TestClass>.Search.In(c => c.TestGuid, testGuids))
.Limit(10)
.ToList();

result.Should().HaveCount(2);
result.Select(s => s.Name).Should().BeEquivalentTo(["test6", "test7"]);
}

[Fact]
public void MoreLikeThis()
{
Expand Down Expand Up @@ -767,6 +806,10 @@ private IMongoCollection<EmbeddedMovie> GetEmbeddedMoviesCollection() => _mongoC
.GetDatabase("sample_mflix")
.GetCollection<EmbeddedMovie>("embedded_movies");

private IMongoCollection<TestClass> GetExtraTestsCollection() => _mongoClient
.GetDatabase("csharpExtraTests")
.GetCollection<TestClass>("testClasses");

[BsonIgnoreExtraElements]
public class Comment
{
Expand Down Expand Up @@ -881,5 +924,22 @@ public class EmbeddedMovie
[BsonElement("score")]
public double Score { get; set; }
}

[BsonIgnoreExtraElements]
private class TestClass
{
[BsonId]
public ObjectId Id { get; set; }

[BsonElement("name")]
public string Name { get; set; }

[BsonElement("testString")]
public string TestString { get; set; }

[BsonGuidRepresentation(GuidRepresentation.Standard)]
[BsonElement("testGuid")]
public Guid TestGuid { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ public void Equals_should_render_supported_type<T>(
new object[] { DateTime.MinValue, "ISODate(\"0001-01-01T00:00:00Z\")", Exp(p => p.Birthday), "dob" },
new object[] { DateTimeOffset.MaxValue, "ISODate(\"9999-12-31T23:59:59.999Z\")", Exp(p => p.DateTimeOffset), nameof(Person.DateTimeOffset) },
new object[] { ObjectId.Empty, "{ $oid: '000000000000000000000000' }", Exp(p => p.Id), "_id" },
new object[] { Guid.Empty, """{ "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAA==", "subType" : "04" } }""", Exp(p => p.Guid), nameof(Person.Guid) },
new object[] { null, "null", Exp(p => p.Name), nameof(Person.Name) },
new object[] { "Jim", "\"Jim\"", Exp(p => p.FirstName), "fn" }
};

Expand Down Expand Up @@ -553,6 +555,7 @@ public void In_typed<T>(
new object[] { new[] { DateTime.MinValue, DateTime.MaxValue }, new[] { "ISODate(\"0001-01-01T00:00:00Z\")", "ISODate(\"9999-12-31T23:59:59.999Z\")" }, Exp(p => p.Birthday), "dob" },
new object[] { new[] { DateTimeOffset.MinValue, DateTimeOffset.MaxValue }, new[] { "ISODate(\"0001-01-01T00:00:00Z\")", "ISODate(\"9999-12-31T23:59:59.999Z\")" }, Exp(p => p.DateTimeOffset), nameof(Person.DateTimeOffset)},
new object[] { new[] { ObjectId.Empty, ObjectId.Parse("4d0ce088e447ad08b4721a37") }, new[] { "{ $oid: '000000000000000000000000' }", "{ $oid: '4d0ce088e447ad08b4721a37' }" }, Exp(p => p.Id), "_id" },
new object[] { new[] { Guid.Empty, Guid.Parse("b52af144-bc97-454f-a578-418a64fa95bf") }, new[] { """{ "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAA==", "subType" : "04" } }""", """{ "$binary" : { "base64" : "tSrxRLyXRU+leEGKZPqVvw==", "subType" : "04" } }""" }, Exp(p => p.Guid), nameof(Person.Guid) },
new object[] { new object[] { (byte)1, (short)2, (int)3 }, new[] { "1", "2", "3" }, Exp(p => p.Object), nameof(Person.Object) }
};

Expand Down Expand Up @@ -1240,7 +1243,7 @@ public class Person : SimplePerson
public float Float { get; set; }
public double Double { get; set; }
public decimal Decimal { get; set; }

public Guid Guid { get; set; }
public DateTimeOffset DateTimeOffset { get; set; }
public TimeSpan TimeSpan { get; set; }

Expand All @@ -1263,6 +1266,8 @@ public class Person : SimplePerson
public string[] Hobbies { get; set; }

public object Object { get; set; }

public string Name { get; set; }
}

public class Family
Expand Down

0 comments on commit de3adba

Please sign in to comment.