private static FilterDefinition <BsonDocument> StringQuery(String parameterName, Operator optor, String modifier, ValueExpression operand) { switch (optor) { case Operator.EQ: var typedOperand = operand.ToUnescapedString(); switch (modifier) { case Modifier.EXACT: return(Builders <BsonDocument> .Filter.Eq(parameterName, typedOperand)); case Modifier.CONTAINS: return(Builders <BsonDocument> .Filter.Regex(parameterName, new BsonRegularExpression(new Regex($".*{typedOperand}.*", RegexOptions.IgnoreCase)))); case Modifier.TEXT: //the same behaviour as :phonetic in previous versions. return(Builders <BsonDocument> .Filter.Regex(parameterName + "soundex", "^" + typedOperand)); //case Modifier.BELOW: // return Builders<BsonDocument>.Filter.Matches(parameterName, typedOperand + ".*") case Modifier.NONE: case null: //partial from begin return(Builders <BsonDocument> .Filter.Regex(parameterName, new BsonRegularExpression("^" + typedOperand, "i"))); default: throw new ArgumentException( $"Invalid modifier {modifier} on string parameter {parameterName}"); } case Operator.IN: //We'll only handle choice like :exact IEnumerable <ValueExpression> opMultiple = ((ChoiceValue)operand).Choices; return(SafeIn(parameterName, new BsonArray(opMultiple.Select(sv => sv.ToUnescapedString())))); case Operator.ISNULL: return(Builders <BsonDocument> .Filter.Or(Builders <BsonDocument> .Filter.Exists(parameterName, false), Builders <BsonDocument> .Filter.Eq(parameterName, BsonNull.Value))); //With only Builders<BsonDocument>.Filter.NotExists, that would exclude resources that have this field with an explicit null in it. case Operator.NOTNULL: return(Builders <BsonDocument> .Filter.Ne(parameterName, BsonNull.Value)); //We don't use Builders<BsonDocument>.Filter.Exists, because that would include resources that have this field with an explicit null in it. default: throw new ArgumentException( $"Invalid operator {optor} on string parameter {parameterName}"); } }