vapor-community / mongo-provider

MongoDB Provider for Vapor
40 stars 18 forks source link

`model.save()` triggers `Unsupported Node type, only array is supported.` #2

Closed honghaoz closed 7 months ago

honghaoz commented 7 years ago

I'm using mongo as my database provider.

When I modify a model and save() it, Unsupported Node type, only array is supported. is logged into the console. But this model can save successfully anyway.

Following is my code:

main.swift

import Vapor
import Foundation
import VaporMongo
import HTTP

let drop = Droplet(
    preparations: [
        User.self,
        Post.self,
    ],
    providers: [
        VaporMongo.Provider.self
    ]
)

// MARK: - Route
// Users
drop.group("/users", closure: UserController().route)

drop.run()

UserController.swift

import Vapor
import HTTP
import Routing

final class UserController: ControllerRouting {
    func route(routeGroup: RouteGroup<Responder, Droplet>) {
        routeGroup.get(handler: showUsers)
        routeGroup.get("*") { request in
            return "404"
        }
    }
}

extension UserController {
    func showUsers(_ req: Request) throws -> ResponseRepresentable {
        var users = try User.all()

        if var foundUser = users.first {
            foundUser.name = "Honghao"
            try foundUser.save()
        } else {
            print("No any User found")
            var newUser = User(name: "Honghao")
            try newUser.save()
            print("Created: \(newUser.id)")
            users = [newUser]
        }

        let usersString = users.map({ $0.name }).joined(separator: ", ")

        return try drop.view.make("users", [
            "user": Node.string(usersString)
            ]
        )
    }
}

User.swift

import Vapor
import Fluent
import Foundation

final class User: Model {
    var name: String

    // MARK: - Entity
    var id: Node?
    var exists: Bool = false

    init(name: String) {
        self.id = UUID().uuidString.makeNode()
        self.name = name
    }

    init(node: Node, in context: Context) throws {
        id = try node.extract("_id")
        name = try node.extract("name")
    }

    func makeNode(context: Context) throws -> Node {
        return try Node(node: [
            "_id": id,
            "name": name
        ])
    }
}

// MARK: - Preparation
extension User {
    static func prepare(_ database: Database) throws {
        // Mongo doesn't need to prepare
    }

    static func revert(_ database: Database) throws { }
}
honghaoz commented 7 years ago

I think this issue should be moved to https://github.com/vapor/fluent

voronianski commented 7 years ago

Experiencing the same issue on saving existing model and mongodb-provider.

tanner0101 commented 7 years ago

~Looks like after the save call the mongo-driver is returning an array of objects instead of the single object that was saved.~

Misread it, it looks like the object being saved just needs to be wrapped in an array first before being returned.

We should fix this in https://github.com/vapor/mongo-driver/pull/26.

Joannis commented 7 years ago

@tannernelson don't you mean it the other way around? It's returning one object instead of an array

tanner0101 commented 7 years ago

@Joannis updated my comment.

Joannis commented 7 months ago

Closing as this library is ancient