How to Filter Regular expression in MongoDB with F# - mongodb

I've tried quite a few different ways of doing this and ultimately I would like to have multiple find filters together.
So - for example, one way would be like https://www.codeproject.com/Articles/1228421/Dynamic-high-performance-Query-builder-for-MongoDB
Trying to build the following C# code in F# ( and converting to my code )
Builders<CustomerGrid>.Filter.Regex(u => u.company,
new BsonRegularExpression(companyColumnText + "*", "I"))
I have tried
let filter1 = Builders<PostDataItem>.Filter.Regex(fun n -> n.reference1,new BsonRegularExpression("1002\d{5}"))
and ( with brackets around field definition )
let filter1 = Builders<PostDataItem>.Filter.Regex((fun n -> n.reference1),new BsonRegularExpression("1002\d{5}"))
Another way of looking at it is to break down the parameters
let fd: FieldDefinition<PostDataItem> = // ?? field = reference1
let re: BsonRegularExpression = new BsonRegularExpression("1002\d{5}")
let filter1 = Builders<PostDataItem>.Filter.Regex(fd,re)
It seems that if I could figure out how to build the field definition then it might work.

You're close. The only problem I see is that the LINQ expression has to have a return type of Object. This happens implicitly in C#, but in F# you have to explicitly cast it:
let filter1 =
Builders<PostDataItem>
.Filter
.Regex(
(fun n -> n.reference1 :> obj),
BsonRegularExpression("1002\d{5}"))
(IMHO, this is just a bit of C# bias baked into their API. Hopefully they’ll fix it one day.)

Related

How to collect mongodb::Cursor into a Vec in rust

I'm trying to use the .find() method in mongodb. The output yeilds a mongodb::Cursor. I'm unable to convert the cursor into a vector so that I can wrap them in a json and send it to my front-end. This is the following idea I've tried
The following error message is:
the trait bound `Vec<user_model::User>: Extend<Result<user_model::User, mongodb::error::Error>>` is not satisfied\nthe following other types implement trait `Extend<A>`
I've already included and use futures::StreamExt; and use futures::TryFutureExt; and tried out .try_next() and .map() instead of .collect(), still cant parse it
Converting an element in the cursor to a User might fail. You may only collect into a Vec of Result with .collect().
let serial: Vec<Result<User, _>> = users.collect().await;
The easy way to get to Vec<User> here would be to use .try_collect(). Just make sure to handle the Err correctly and not just use unwrap as I've done here.
let serial: Vec<User> = users.try_collect().await.unwrap();
Here is how I managed this in one of my projects.
I simply iterate over the cursor calling next and push each item in a vector. I used the Document type to collect the results.
Using a match for each result allows to handle the errors properly, because extraction may fail.
let mut results: Vec<Document> = Vec::new();
while let Some(result) = cursor.next().await {
match result {
Ok(document) => {
results.push(document);
}
_ => {
return HttpResponse::InternalServerError().finish();
}
}
}

F# Async<_> to Async<obj>

I am working with F# to develop PowerShell tooling. I am currently running into a block because Async<_>is a generic type that is not derived from a non-generic type, so I can't request an Async<_> or Async as a parameter value - I have to specify the exact generic type parameter.
(For those unfamiliar with the interaction between these two languages, I can write a class in a .NET language such as F#, derive it from a class in the PowerShell library, and give it a specific attribute and when I run PowerShell and import my library, my class is exposed as a command. The command type can't be generic. Properties of the type are exposed as PowerShell parameters.)
As far as I'm aware I can't avoid this by having a generic member on a non-generic type, so ideally I'd have a transformation attribute (for non-PS users, transformation attributes effectively perform type conversion during runtime parameter binding) to turn Async<_> into Async<obj>. For the most part, this would work great for me. However, I can't figure out a way to check if a value is Async<_>, because the check computation :? Async<_> at compile time ends up as computation :? Async<obj>, which is not, unfortunately, the same, and returns false when passed Async<int>.
I ran into a similar issue in C# and was able to leverage the dynamic keyword after running a reflection test, and making the parameter be of the derived base type System.Threading.Tasks.Task, e.g.
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHeirarchy;
var isTaskOf = task.GetType()
.GetProperty("GetAwaiter", flags)
.PropertyType
.GetMethod("GetResult", flags)
.ReturnType != typeof(void);
if (isTaskOf) {
var result = await (dynamic)task;
}
I am willing to do something like this in F# if possible, but:
I have not ben able to successfully get the dynamic lookup operator ? to compile. Specifically, "none of the types 'Async<'a>, string' support the '?' operator". Not sure what I'm doing wrong as the explanations look straightforward and I can't find any other reports of this message or requirements for that operator.
I don't know if that would even work or if that operator is only used to dynamically access a member of an object.
The solutions I have tried are:
/// Transform from Async<_> to Async<obj>
override _.Transform(_, item : obj) : obj =
match item with
// only matches Async<obj>. I get a compiler warning that _ is constrained to obj
| :? Async<_> as computation ->
let boxedComputation : Async<obj> = async { return! computation }
boxedComputation
// if the value is not an async computation, let it pass through. This will allow other transformation or type converters to try to convert the value
| _ -> item
override _.Transform(_, item) =
// no compiler warning about the type being constrained to obj, but the if test does not pass unless item is Async<obj>
if (item :? Async<_>) then async { return! item :?> Async<_> }
else item
The other thing I can think of is to use reflection entirely - get the async type, call all of the AsyncBuilder methods reflectively to create a computation expression, and then cast it to Async. As I'm fairly new to F# I'm not sure how well I'd be able to piece together a computation expression like that, and either way it seems a lot more complicated than it ought to be. I'm hoping there is some better way to identify the return type of an async computation and/or just box the result without caring what type it actually is.
EDIT
After trying something ridiculously complicated using reflection with the AsyncBuilder type I realized I could leverage it a little more simply. Here is my current working solution, but I'm still looking out for any better options.
static let boxAsyncReturnValue v = async { return v :> obj }
static let bindFunctionReflected = typeof<FSharpAsyncObjTransformationAttribute>.GetMethod(
nameof boxAsyncReturnValue,
BindingFlags.NonPublic ||| BindingFlags.Static
)
override _.Transform(engineIntrinsics, item) =
// I need to identify the current return type of the computation, and quit if "item" is not Async<_>
if item = null then item else
let itemType = item.GetType()
if not itemType.IsGenericType then item else
let genericItemType = itemType.GetGenericTypeDefinition()
if genericItemType <> typedefof<Async<_>> then item else
let returnType = itemType.GetGenericArguments()[0]
if returnType = typeof<obj> then item else
bindFunctionReflected.MakeGenericMethod(itemType).Invoke(null, [|item|])
This is how I would do it:
let convert (a: Async<_>) =
async {
let! x = a
return box x
}
And at compile time it behaves as you'd expect:
let a = async { return "hello" }
let o: Async<obj> = convert a
let res = Async.RunSynchronously o
printfn "%s" res // Error: expected type 'string' but is type 'obj'
printfn "%s" (unbox<string> res) // compiles, prints the string

what is the best way to write this function? [duplicate]

just a short question. In Swift it is possible to solve the following code:
var a: String;
a = "\(3*3)";
The arithmetic operation in the string will be solved. But i can´t figure out, why this following variation doesn´t work.
var a: String;
var b: String;
b = "3*3";
a = "\(b)";
In this case the arithmetic operation in var a will not be resolved. Any ideas why and how i can this get to work. Some things would be much more easier if this would work. Thanks for your answers.
In the second case, you are interpolating a string, not an arithmetic expression. In your example, it's a string you chose at compile time, but in general it might be a string from the user, or loaded from a file or over the web. In other words, at runtime b could contain some arbitrary string. The compiler isn't available at runtime to parse an arbitrary string as arithmetic.
If you want to evaluate an arbitrary string as an arithmetic formula at runtime, you can use NSExpression. Here's a very simple example:
let expn = NSExpression(format:"3+3")
println(expn.expressionValueWithObject(nil, context: nil))
// output: 6
You can also use a third-party library like DDMathParser.
Swift 4.2
let expn = "3+3"
print(expn.expressionValue(with: nil, context: nil))
But I also have a solution thats not the most effective way but could be used in some cases if your sure it's only "y+x" and not longer string.
var yNumber: Int!
var xNumber: Int!
let expn: String? = "3+3"
// Here we take to first value in the expn String.
if let firstNumber = expo?.prefix(1), let myInt = Int(firstNumber){
// This will print (Int : 3)
print("Int : \(myInt)")
// I set the value to yNumber
yNumber = myInt
}
// Here we take the last value in the expn string
if let lastNumber = optionalString?.suffix(1), let myInt = Int(lastNumber){
// This will print (Int : 3)
print("Int : \(myInt)")
// I set the value to xNumber
xNumber = myInt
}
// Now you can take the two numbers and add
print(yNumber + xNumber)
// will print (6)
I can't recommend this but it works in some cases
This won't be solved because this is not an arithmetic operation, this is a string:
"3*3"
the same as this
"String"
Everything you put in " it's a string.
The second example lets you construct a new String value from a mix of constants, variables, literals, and expressions:
"\(3*3)"
this is possible because of string interpolation \()
You inserted a string expression which swing convert and create expected result.
You can try to use evaluatePostfixNotationString method from that class.
The whole project is about recognizing math expression from camera image and calculating it after.

MongoDb and F#: How to select distinct values?

I'm using the latest (at the time of writing) version (2.8) of the C# MongoDb driver.
I am using it from F#.
I want to select the distinct values of a field in a collection.
From this old question, the following does not work:
let client = new MongoClient(connString)
let db = client.GetDatabase("AirQuality")
let col = db.GetCollection<ReadingValue>("ReadingValue")
let res = col.DistinctAsync<string>("SensorName","{}")
The type string is not compatible with the type FieldDefinition<ReadingValue,string>.
From this answer, the following does not work either
let fd : FieldDefinition<ReadingValue, string> = "" :> FieldDefinition<ReadingValue, string>
In C# you can implicitly convert from string to FieldDefinition<T> (class implements implicit operator). Since types conversion works in a different way in F# you can use StringFieldDefinitionClass
let field = new StringFieldDefinition<ReadingValue, string>("SensorName")
let result = col.Distinct<string>(field, Builders<ReadingValue>.Filter.Empty)

Why doesn't swift allow for let-based decisions in ternaries?

It's possible to do the following in Swift:
let params: String
if let aString = someOptionalString {
params = "?someparam=\(aString)"
} else {
params = ""
}
However it would be much more concise if I could write it like:
let params = let aString = someOptionalString ? "?someparam=\(aString)" : ""
Or
let params = case let aString = someOptionalString ? "?someparam=\(aString)" : ""
However this doesn't compile in any way I could think about. Is this possible? If not, why not? And is there a way to suggest it to be implemented or can I only try to first add this myself to the Swift project and then propose the change to the community?
Because mapping an optional is a much more sensible choice:
let params = someOptionalString.map{ "?someparam\($0)" } ?? ""
To answer your question as given, conditional let only applies in an if statement or similar branching construct, everywhere else it doesn't have a value.
Normally when you have a pattern like:
if let x = y {
doSomething(x)
}
...what you're doing is declaring a new namespace context inheriting from the current one where x is defined; whether the code enters that context depends on whether the assigning expression evaluates to nil. Outside the block, x is not defined and it's an error to refer to it. If you like, think of it as a closure, something that might look like:
callIfNotNil(y, {x in doSomething(x)})
When you do a let otherwise, you are defining it in the current namespace, which means it can't not be defined on the other side of the ternary operator, so the best the compiler could give you is String! as a type, which would defer the nil check to runtime, largely defeating the point of using it.
In principle ternary could apply the same behaviour by defining an implicit block in the middle of the expression, but that's a recipe for confusion on the part of the programmer.
As for why let x = true; let y = x ? 1 : 2 is valid but let y = let x = true ? 1 : 2 isn't, there are some trivial precedence problems there, and with the let keyword being a compile-time feature not a runtime one it would be misleading to allow it mid-expression.