Mongo C# driver - Contains Filter
Asked Answered
L

6

13

I am using the latest version of Mongo C# driver which uses a lot of Async and builder pattern. Which is nice. I am trying to convert SQL where clauses into Mongo FilterDefinition object.

Any idea how to handle "contains"?
like:

where x contains 'ABC'
Linguiform answered 21/8, 2015 at 10:58 Comment(0)
S
7

If x is a string, you could do so with a simple regex. For the 2.0 driver, you can manually create the FilterDefinition:

FilterDefinition<BsonDocument> filter = "{ x : { $regex : /ABC/ } }";

Or build the filter use the Builder:

var builder = Builders<BsonDocument>.Filter;
var filter = builder.Matches("x", "ABC");

Then you can use the filter in your query:

using (var cursor = await collection.Find(filter).ToCursorAsync())
{
    // ...
}
Stoichiometric answered 21/8, 2015 at 11:8 Comment(1)
Thanks! I am using 2.0 version of driver and could not .Matches() on Filter Builder, but I could find .Regex(), so I'll try with that.Linguiform
R
19

In order to achieve that in V2 API, use the `Filter.Regex':

var collection = db.GetCollection<BsonDocument>("collection");

var filter = Builders<BsonDocument>.Filter.Regex("fieldName", new BsonRegularExpression(".*fieldValue.*"));

var data = await (await coll.FindAsync<BsonDocument>(filter).ConfigureAwait(false)).ToListAsync();

//continue process data 
Redouble answered 6/4, 2016 at 8:47 Comment(0)
S
7

If x is a string, you could do so with a simple regex. For the 2.0 driver, you can manually create the FilterDefinition:

FilterDefinition<BsonDocument> filter = "{ x : { $regex : /ABC/ } }";

Or build the filter use the Builder:

var builder = Builders<BsonDocument>.Filter;
var filter = builder.Matches("x", "ABC");

Then you can use the filter in your query:

using (var cursor = await collection.Find(filter).ToCursorAsync())
{
    // ...
}
Stoichiometric answered 21/8, 2015 at 11:8 Comment(1)
Thanks! I am using 2.0 version of driver and could not .Matches() on Filter Builder, but I could find .Regex(), so I'll try with that.Linguiform
Y
3

I was able to get this working using Filter.AnyIn like so

var filter = Builders<BsonDocument>.Filter.AnyIn("x", new List<string> { "ABC" });

This works if you're looking for multiple values too, just add them to the list.

Yager answered 22/11, 2019 at 19:35 Comment(0)
K
1

First, I highly recommend taking MongoDB University's .NET course (from Mongo itself). It's really thorough, and covers your question (and more) in depth.

Second, I assume that x is an array in your example.

MongoDB correctly handles polymorphism with arrays. If you have a class Post with an array of Tags, you can filter where Tag = ABC.

If you're using the C# linq methods, that looks like .Find(p => p.Tags == "ABC"). If you're using BsonDocument, that looks like new BsonDocument().Add("Tags", "ABC").

Kreisler answered 21/8, 2015 at 11:6 Comment(0)
M
1

If you want to just search input text you need to replace regex special characters.

Regex.Escape will ensure that these characters are processed literally rather than as metacharacters. Otherwise input text can be used to query regex patterns which is probably not what is required.

var text = "ABC";
var filter = Builders<BsonDocument>.Filter.Regex("x", BsonRegularExpression.Create(Regex.Escape(text)));

If you need case insensitive check. Then you can pass case insensitive regex to BsonRegularExpression.Create:

var text = "ABC";
var escapeText = Regex.Escape(text);
var regex = new Regex(escapeText, RegexOptions.IgnoreCase);
var filter = Builders<BsonDocument>.Filter.Regex("x", BsonRegularExpression.Create(regex));
Monogenetic answered 16/8, 2021 at 20:55 Comment(0)
S
0

I have another way which I don't love but it works. The answer that is marked correct is half wrong (Matches is a method of Builders). In this example the / act like a % in a sql query LIKE statement. I'm still looking for a better way and will update if I find one that is more Equals filter below.

List<yourobject> someList = await collection.Find("{ x: /Test/ }").ToListAsync();

var filter = Builders<yourobject>.Filter.Eq("x", "ABC");
List<yourobject> someList = await collection.Find(filter).ToListAsync();
Stillage answered 15/11, 2015 at 20:17 Comment(1)
Your builder method for the filter isn't correct. It cannot be Equal to since you're looking for Contains.Vinegar

© 2022 - 2024 — McMap. All rights reserved.