2016-11-29 29 views
0

给予一定的一UserRepository斯卡拉 - 筛选失败一定条件

class UserRepository { 

    val collection = Mongo.connect("users") 

    def findBy(key: String, value: String): Future[Option[User]] = { 
    collection.flatMap(
     _.find(document(key -> value)).one[User] 
    ) 
    } 
} 

我想写一个login方法:

def login(email: String, password: String): Future[Option[User]] = { 
    import scala.concurrent.ExecutionContext.Implicits.global 

    repo.findBy("email", email) 
    // .filter { user => BCrypt.checkpw(password, user.password) } 
} 

如何将我写的findBy到结果的映射如果他们测试失败BCrypt.checkpw(password, user.password),将所有Some(user)的变成None?我能做些什么来改变None失败的Some

+0

你就不能使用您注释掉'filter'法:在它的签名(Option[User])你可能想这已经说明?它有什么问题? – marstran

+0

直接进入过滤器的问题是该值是'Some'或'None',因此只需执行'BCrypt.checkpw(password,user.password)'抛出: '编译错误[value password is不是Option [authentication.User]]的成员' – danbroooks

+0

当然,我可以在过滤器内部做一个匹配,我只是想知道是否有什么比模式匹配更好用在这里?感觉有点奇怪,执行模式匹配,然后只是返回另一个“选项”(这可能只是我的思路,在这种情况下这是一个完全合理的事情) – danbroooks

回答

2

使用收集并使用模式匹配警卫来检查用户。如果用户无法再返回无

findBy(key, value).collect { 
    case Some(user) if ! BCrypt.checkpw(password, user.password) => None 
} 

建议

这将是很好的收集用户满足条件这样你的最终输出类型将Future[user]而不是Future[Option[User]]。当然,在收集您的Future[Option[User]]之后,将会包含Some(user),其中user是有效的用户。

findBy(key, value).collect { 
    case Some(user) if BCrypt.checkpw(password, user.password) => user 
} 

该行给出唯一有效的用户和最终的类型将是Future[User]而不是Future[Option[User]]

+0

如果没有用户匹配'findBy',会发生什么? – danbroooks

+0

@danbroooks它会给你'没有' – 2016-11-29 16:16:19

+0

@danbroooks'未来'将有'没有'。正如第一种情况和第二种情况一样,您将得到'java.util.NoSuchElementException'。当然,异常将被包裹在未来中。选择你想要使用的。 – pamu

3

您需要映射在FutureSome改变其值设置为None。过滤器的调用需要进入传递给map函数的函数内部。试试这个:

def login(email: String, password: String): Future[Option[User]] = { 
    import scala.concurrent.ExecutionContext.Implicits.global 

    repo.findBy("email", email) 
     .map { userOpt => userOpt.filter(user => BCrypt.checkpw(password, user.password)) } 
} 
+1

f。克的答案是清洁的,但。至少这表明你最初的尝试有什么问题。 – marstran

3

你可能不希望在Futurefilter/collect,因为你会得到一个失败的未来(有例外),然后你需要.recover等。由于你的操作结果

repo.findBy("email", email).map { userOpt => 
    val maybeUser1 = userOpt.filter { user => BCrypt.checkpw(password, user.password) } 

    // or like this: 
    // longer form, if more than one options or whatever 
    val maybeUser2 = for { 
    user <- userOpt 
    if(BCrypt.checkpw(password, user.password)) 
    } yield user 
} 
+0

有了这个,我得到'类型不匹配; found:scala.concurrent.Future [Option [authentication.User]] required:Option [authentication.User]' – danbroooks

+0

然后'findBy(“email”,email)。** flatMap **'? xD –

+0

然后我得到'类型不匹配; found:Option [authentication.User] required:scala.concurrent.Future [?]':/ – danbroooks