Skip to content

Commit de3adba

Browse files
authored
CSHARP-4938: Support for indexing and querying on UUID and null datatype (#1563)
1 parent ee12544 commit de3adba

File tree

4 files changed

+73
-5
lines changed

4 files changed

+73
-5
lines changed

src/MongoDB.Driver/Search/OperatorSearchDefinitions.cs

+3
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ private static BsonValue ToBsonValue(TField value) =>
145145
DateTime v => (BsonDateTime)v,
146146
DateTimeOffset v => (BsonDateTime)v.UtcDateTime,
147147
ObjectId v => (BsonObjectId)v,
148+
Guid v => new BsonBinaryData(v, GuidRepresentation.Standard),
148149
string v => (BsonString)v,
150+
null => BsonNull.Value,
149151
_ => throw new InvalidCastException()
150152
};
151153
}
@@ -259,6 +261,7 @@ private static BsonValue ToBsonValue(TField value) =>
259261
DateTimeOffset v => (BsonDateTime)v.UtcDateTime,
260262
string v => (BsonString)v,
261263
ObjectId v => (BsonObjectId)v,
264+
Guid v => new BsonBinaryData(v, GuidRepresentation.Standard),
262265
_ => throw new InvalidCastException()
263266
};
264267
}

src/MongoDB.Driver/Search/SearchDefinitionBuilder.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public SearchDefinition<TDocument> EmbeddedDocument<TField>(
111111
/// <summary>
112112
/// Creates a search definition that queries for documents where an indexed field is equal
113113
/// to the specified value.
114-
/// Supported value types are boolean, numeric, ObjectId, date and string.
114+
/// Supported value types are null, boolean, numeric, ObjectId, Guid, date and string.
115115
/// </summary>
116116
/// <typeparam name="TField">The type of the field.</typeparam>
117117
/// <param name="path">The indexed field to search.</param>
@@ -127,7 +127,7 @@ public SearchDefinition<TDocument> Equals<TField>(
127127
/// <summary>
128128
/// Creates a search definition that queries for documents where an indexed field is equal
129129
/// to the specified value.
130-
/// Supported value types are boolean, numeric, ObjectId, date and string.
130+
/// Supported value types are null, boolean, numeric, ObjectId, Guid, date and string.
131131
/// </summary>
132132
/// <typeparam name="TField">The type of the field.</typeparam>
133133
/// <param name="path">The indexed field to search.</param>
@@ -316,7 +316,7 @@ public SearchDefinition<TDocument> GeoWithin<TCoordinates>(
316316
/// <summary>
317317
/// Creates a search definition that queries for documents where the value of the field equals to any of specified values.
318318
/// </summary>
319-
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, number, date, string.</typeparam>
319+
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, Guid, number, date, string.</typeparam>
320320
/// <param name="path">The indexed field or fields to search.</param>
321321
/// <param name="values">Values to compare the field with.</param>
322322
/// <param name="score">The score modifier.</param>
@@ -330,7 +330,7 @@ public SearchDefinition<TDocument> In<TField>(
330330
/// <summary>
331331
/// Creates a search definition that queries for documents where the value of the field equals to any of specified values.
332332
/// </summary>
333-
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, number, date, string.</typeparam>
333+
/// <typeparam name="TField">The type of the field. Valid types are: boolean, ObjectId, Guid, number, date, string.</typeparam>
334334
/// <param name="path">The indexed field or fields to search.</param>
335335
/// <param name="values">Values to compare the field with.</param>
336336
/// <param name="score">The score modifier.</param>

tests/MongoDB.Driver.Tests/Search/AtlasSearchTests.cs

+60
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,28 @@ public void EmbeddedDocument()
131131
}
132132
}
133133

134+
[Fact]
135+
public void EqualsGuid()
136+
{
137+
var testGuid = Guid.Parse("b52af144-bc97-454f-a578-418a64fa95bf");
138+
139+
var result = GetExtraTestsCollection().Aggregate()
140+
.Search(Builders<TestClass>.Search.Equals(c => c.TestGuid, testGuid))
141+
.Single();
142+
143+
result.Name.Should().Be("test6");
144+
}
145+
146+
[Fact]
147+
public void EqualsNull()
148+
{
149+
var result = GetExtraTestsCollection().Aggregate()
150+
.Search(Builders<TestClass>.Search.Equals(c => c.TestString, null))
151+
.Single();
152+
153+
result.Name.Should().Be("testNull");
154+
}
155+
134156
[Fact]
135157
public void EqualsArrayField()
136158
{
@@ -266,6 +288,23 @@ public void In()
266288
results[1].Runtime.Should().Be(31);
267289
}
268290

291+
[Fact]
292+
public void InGuid()
293+
{
294+
var testGuids = new[]
295+
{
296+
Guid.Parse("b52af144-bc97-454f-a578-418a64fa95bf"), Guid.Parse("84da5d44-bc97-454f-a578-418a64fa937a")
297+
};
298+
299+
var result = GetExtraTestsCollection().Aggregate()
300+
.Search(Builders<TestClass>.Search.In(c => c.TestGuid, testGuids))
301+
.Limit(10)
302+
.ToList();
303+
304+
result.Should().HaveCount(2);
305+
result.Select(s => s.Name).Should().BeEquivalentTo(["test6", "test7"]);
306+
}
307+
269308
[Fact]
270309
public void MoreLikeThis()
271310
{
@@ -767,6 +806,10 @@ private IMongoCollection<EmbeddedMovie> GetEmbeddedMoviesCollection() => _mongoC
767806
.GetDatabase("sample_mflix")
768807
.GetCollection<EmbeddedMovie>("embedded_movies");
769808

809+
private IMongoCollection<TestClass> GetExtraTestsCollection() => _mongoClient
810+
.GetDatabase("csharpExtraTests")
811+
.GetCollection<TestClass>("testClasses");
812+
770813
[BsonIgnoreExtraElements]
771814
public class Comment
772815
{
@@ -881,5 +924,22 @@ public class EmbeddedMovie
881924
[BsonElement("score")]
882925
public double Score { get; set; }
883926
}
927+
928+
[BsonIgnoreExtraElements]
929+
private class TestClass
930+
{
931+
[BsonId]
932+
public ObjectId Id { get; set; }
933+
934+
[BsonElement("name")]
935+
public string Name { get; set; }
936+
937+
[BsonElement("testString")]
938+
public string TestString { get; set; }
939+
940+
[BsonGuidRepresentation(GuidRepresentation.Standard)]
941+
[BsonElement("testGuid")]
942+
public Guid TestGuid { get; set; }
943+
}
884944
}
885945
}

tests/MongoDB.Driver.Tests/Search/SearchDefinitionBuilderTests.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ public void Equals_should_render_supported_type<T>(
312312
new object[] { DateTime.MinValue, "ISODate(\"0001-01-01T00:00:00Z\")", Exp(p => p.Birthday), "dob" },
313313
new object[] { DateTimeOffset.MaxValue, "ISODate(\"9999-12-31T23:59:59.999Z\")", Exp(p => p.DateTimeOffset), nameof(Person.DateTimeOffset) },
314314
new object[] { ObjectId.Empty, "{ $oid: '000000000000000000000000' }", Exp(p => p.Id), "_id" },
315+
new object[] { Guid.Empty, """{ "$binary" : { "base64" : "AAAAAAAAAAAAAAAAAAAAAA==", "subType" : "04" } }""", Exp(p => p.Guid), nameof(Person.Guid) },
316+
new object[] { null, "null", Exp(p => p.Name), nameof(Person.Name) },
315317
new object[] { "Jim", "\"Jim\"", Exp(p => p.FirstName), "fn" }
316318
};
317319

@@ -553,6 +555,7 @@ public void In_typed<T>(
553555
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" },
554556
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)},
555557
new object[] { new[] { ObjectId.Empty, ObjectId.Parse("4d0ce088e447ad08b4721a37") }, new[] { "{ $oid: '000000000000000000000000' }", "{ $oid: '4d0ce088e447ad08b4721a37' }" }, Exp(p => p.Id), "_id" },
558+
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) },
556559
new object[] { new object[] { (byte)1, (short)2, (int)3 }, new[] { "1", "2", "3" }, Exp(p => p.Object), nameof(Person.Object) }
557560
};
558561

@@ -1240,7 +1243,7 @@ public class Person : SimplePerson
12401243
public float Float { get; set; }
12411244
public double Double { get; set; }
12421245
public decimal Decimal { get; set; }
1243-
1246+
public Guid Guid { get; set; }
12441247
public DateTimeOffset DateTimeOffset { get; set; }
12451248
public TimeSpan TimeSpan { get; set; }
12461249

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

12651268
public object Object { get; set; }
1269+
1270+
public string Name { get; set; }
12661271
}
12671272

12681273
public class Family

0 commit comments

Comments
 (0)