[CSHARP-1884] In should still work when TField is not exactly right (like it used to) Created: 06/Jan/17  Updated: 02/Jun/22  Resolved: 27/Jan/17

Status: Closed
Project: C# Driver
Component/s: API
Affects Version/s: 2.4.1
Fix Version/s: 2.4.2

Type: Bug Priority: Major - P3
Reporter: Gian Maria Ricci Assignee: Robert Stam
Resolution: Done Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to CSHARP-1891 Distinct should still work when TFiel... Closed

 Description   

Take this little class

public class Post
{
    public String Id { get; set; }
    public String Title { get; set; }
    public String[] Tags { get; set; }
}

Notice that the TAGS property is an array of string.

And now this query that runs perfectly fine with 2.4.0 version or earlier

var result = _collection.Find(
    Builders<Post>.Filter.In("Tags", new[] { "Tag1" }))
    .ToList();

I know that this query is not really correct, because it should use the AnyIn operator, but it runs fine with every version of 2.x driver up to 2.4.0, and also if you know Mongo javascript api you are perfectly fine issuing an $in query for a property that is an array of string.

Now if you upgrade the driver to 2.4.1 the above query have an error.

Test 'NewDriver.Query.InOnArray.verify_in_query' failed: System.InvalidCastException : Unable to cast object of type 'System.String' to type 'System.String[]'.
	at MongoDB.Driver.FieldValueSerializerHelper.CastingSerializer`2.Serialize(BsonSerializationContext context, BsonSerializationArgs args, TFrom value)
	at MongoDB.Bson.Serialization.IBsonSerializerExtensions.Serialize[TValue](IBsonSerializer`1 serializer, BsonSerializationContext context, TValue value)
	at MongoDB.Driver.SingleItemAsArrayOperatorFilterDefinition`2.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry)
	at MongoDB.Driver.MongoCollectionImpl`1.CreateFindOperation[TProjection](FilterDefinition`1 filter, FindOptions`2 options)
	at MongoDB.Driver.MongoCollectionImpl`1.FindSync[TProjection](FilterDefinition`1 filter, FindOptions`2 options, CancellationToken cancellationToken)
	at MongoDB.Driver.FindFluent`2.ToCursor(CancellationToken cancellationToken)
	at MongoDB.Driver.IAsyncCursorSourceExtensions.ToList[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)
	C:\Users\GianMariaRicci\Source\Repos\MongoDbNewDriverTest\NewDriver\Query\InOnArray.cs(56,0): at NewDriver.Query.InOnArray.verify_in_query()

I know that the query should be really changed to AnyIn, but this is a breaking compatibility with version 2.4.0 and it requires at least a change in minor driver number.



 Comments   
Comment by Githook User [ 27/Jan/17 ]

Author:

{u'username': u'rstam', u'name': u'rstam', u'email': u'robert@robertstam.org'}

Message: CSHARP-1884: Make In filter method changes backward compatible.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/ceac8f76a3b0bd1fcdabf3e9f298870b0be097c2

Comment by Robert Stam [ 14/Jan/17 ]

https://mongodbcr.appspot.com/117160001/

Comment by Robert Stam [ 13/Jan/17 ]

This is due to the same underlying issue of CSHARP-1891.

Comment by Robert Stam [ 06/Jan/17 ]

The problem is with this line:

var filter = builder.In("Tags", new[] { "Tag1" });

The compiler is inferring that the field is of type string, so what the compiler sees is:

var filter = builder.In<string>("Tags", new[] { "Tag1" }); // note: In<string>

but the actual field is of type string[]. If we tell the compiler the correct type of the field then we get a compile time error:

var filter = builder.In<string[]>("Tags", new[] { "Tag1" }); // note: In<string[]>

I believe this was only working "by accident" in 2.4.0. The In method is only intended to be used with scalar fields (not array fields).

Comment by Robert Stam [ 06/Jan/17 ]

I can reproduce this without calling Find by calling Render:

var builder = Builders<Post>.Filter;
var filter = builder.In("Tags", new[] { "Tag1" });
var documentSerializer = BsonSerializer.LookupSerializer<Post>();
var serializerRegistry = BsonSerializer.SerializerRegistry;
var json = filter.Render(documentSerializer, serializerRegistry).ToJson();

In version 2.4.0 of the driver this renders as:

"{ \"Tags\" : { \"$in\" : [\"Tag1\"] } }"

And in version 2.4.1 it throws the exception that you reported.

Generated at Wed Feb 07 21:40:56 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.