如何将元素添加到嵌套数组

时间:2019-04-12 08:30:11

标签: mongodb f#

当我尝试将商品添加到这样的列表中时:

open MongoDB.Driver

type SegmentId = string

type SegmentRM =
    { id : SegmentId      
      users: string list }

let addUserToSegment (collection : IMongoCollection<SegmentRM>) (id: SegmentId) (usr: string) =
    let filter = Builders.Filter.Eq((fun x -> x.id), id)
    let update = Builders.Update.Push<string>((fun x -> x.users), usr)
    collection.UpdateOneAsync(filter, update)

我有一个编译错误 No overloads match for method 'Push'. The available overloads are shown below. 并且也尝试对users: string[]进行同样的错误处理。 有人知道如何避免这种编译错误吗?

2 个答案:

答案 0 :(得分:1)

编译器错误表明string listIEnumerable<string>不兼容。但是string seq是这样,因此您应该按照以下方式定义类型

type SegmentRM =
    { id : SegmentId      
      users: string seq }

答案 1 :(得分:1)

假设您调用此Builders.Update.Push方法,则必须直接或通过调用Seq.ofList来显式将列表强制转换或转换为序列:

[<CompiledName("OfList")>]
let ofList (source : 'T list) =
    (source :> seq<'T>)

常见且可读性更高的方法是使用Seq.ofList,因此您应该使用:

let update = Builders.Update.Push<string>((fun x -> x.users |> Seq.ofList), usr)

说明

这样做的原因是Push需要一个返回IEnumerable<T>的函数。它的语法是:

static member Push : 
    memberExpression : Expression<Func<'TDocument, IEnumerable<'TValue>>> * 
    value : 'TValue -> UpdateBuilder<'TDocument> 

列表does implement the IEnumerable<T> interface

type List<'T> = 
   | ([])  :                  'T list
   | (::)  : Head: 'T * Tail: 'T list -> 'T list
   interface System.Collections.Generic.IEnumerable<'T>
   ...

在问题的情况下,F#编译器无法隐式转换为接口。

另一方面,seqa type alias for IEnumerable<T>

type seq<'T> = IEnumerable<'T> 

Seq.ofList会将users列表投射到IEnumerable<string>期望的Push

相关问题