Skip to content

CSHARP-4938: Support for indexing and querying on UUID and null datatype #1563

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the extra line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean to have both attributes on one line?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh sorry it's all good, on the smaller laptop screen it seemed like there is an extra empty line.

[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) },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'Raw string literals', nice feature! TIL

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