如何在不定义模式的情况下使用Mongoose?

151

在Mongoose(用于node.js)的先前版本中,有一个选项可以在不定义模式的情况下使用它。

var collection = mongoose.noSchema(db, "User");

但是在当前版本中,“noSchema”函数已被删除。我的模式可能经常更改,并且真的不适合定义好的模式,那么在mongoose中是否有一种新的方法可以使用无模式模型?


3
请直接使用Mongodb,它默认为无模式(schema less)。 - Simon Dragsbæk
createConnection() 实例的集合方法怎么样? - Curious Flower
8个回答

229

我认为这就是你正在寻找的 Mongoose Strict

选项:严格模式

默认情况下启用的 strict 选项确保不保存未在模式中指定的值添加到我们的模型实例中。

注意:除非有充分的理由,否则不要将其设置为 false。

    var thingSchema = new Schema({..}, { strict: false });
    var Thing = mongoose.model('Thing', thingSchema);
    var thing = new Thing({ iAmNotInTheSchema: true });
    thing.save() // iAmNotInTheSchema is now saved to the db!!

2
你救了我的一天。我还发现这个不能与#markMotified('<columnName>')一起使用。 - allenhwkim
8
由于此方法无法将更改持久化到数据库中,因此您需要执行thing.set(key, value)而不是thing.key=value - laggingreflex
5
如果您使用这种方法,检索文档时可能会出现问题。在执行查找操作后,再调用 doc.someProp 时,doc.someProp 将会是 undefined,尽管实际上它已经存在于对象中(console.log 确认了这一点),这是因为 mongoose 定义了自己的 getters,似乎只有在模式上定义了该属性才能正常工作。 - Melbourne2991
1
@a20:我理解你关于MySQL的说法 :) 我认为Jonathan的建议/根据Mongoose API文档的说明__注意:除非你有充分的理由,否则不要将其设置为false__。在当前上下文中(仅关于NO-SQL)是完全可以的。 - Amol M Kulkarni
6
@Melbourne2991,这在一定程度上是正确的,但我找到了一个解决办法。您可以在检索到的文档上调用toJSON()方法,然后就可以使用常规的点表示法,如doc.someProp。很抱歉回复了这么旧的答案,只是想在有人遇到相同问题时添加这个信息。 https://mongoosejs.com/docs/guide.html#toJSON - Chris
显示剩余3条评论

68

实际上在Mongoose中,“Mixed” (Schema.Types.Mixed) 模式似乎正好能做到这一点...

它接受一个无需模式定义自由形式的JS对象 - 因此你可以随便放什么在里面。不过似乎需要手动触发该对象的保存,但这似乎是一个公平的权衡。

Mixed

"任何事物都可以"的SchemaType,其灵活性使得它更难以维护。Mixed可通过Schema.Types.Mixed或通过传递空的对象字面量来使用。以下两种方式是等效的:

var Any = new Schema({ any: {} });
var Any = new Schema({ any: Schema.Types.Mixed });

由于混合类型是无模式的,因此您可以将值更改为任何其他值,但Mongoose会失去自动检测和保存这些更改的能力。要“告诉”Mongoose混合类型的值已更改,请调用文档的.markModified(path)方法,并将刚刚更改的混合类型的路径传递给它。

person.anything = { x: [3, 4, { y: "changed" }] };
person.markModified('anything');
person.save(); // anything will now get saved

1
这仍然是使用Mongo/Mongoose无模式工作的正确方式吗? - a20
9
但是这种结构将整个对象嵌套在any字段下面,因此它实际上具有一个模式。更好的答案是像这个答案所说,使用strict: false - steampowered

18

嗨Chris,看看Mongous。我在开发中遇到了和mongoose一样的问题,因为我的Schemas现在非常频繁地变化。Mongous让我保持了Mongoose的简单性,同时能够宽松定义和更改我的'schemas'。我选择创建标准的JavaScript对象并将它们存储在数据库中,如下所示

function User(user){
  this.name = user.name
, this.age = user.age
}

app.post('save/user', function(req,res,next){
  var u = new User(req.body)
  db('mydb.users').save(u)
  res.send(200)
  // that's it! You've saved a user
});

这比Mongoose要简单得多,虽然我确信你会错过一些很酷的中间件功能,比如"pre"。但是我并不需要这些。希望这可以帮到你!


1
你知道如何处理mongous中的错误吗?文档中有些遗漏。 - user187676
4
我认为这不是对问题的真正回答,@kwhitley给出了关于Mongoose的适当回答。 - janex
我必须同意。不过,我不确定在OP提出这个问题时Schema.types.mixed是否可用。 - Hacknightly
楼主在这里,我倾向于同意你的观点,然而,这个答案是在我已经接受了这个答案一年之后才出现的。 - Christopher Tarquini

6

以下是详细说明: [https://www.meanstack.site/2020/01/save-data-to-mongodb-without-defining.html][1]

在不定义模式的情况下将数据保存到MongoDB
    const express = require('express')()
    const mongoose = require('mongoose')
    const bodyParser = require('body-parser')
    const Schema = mongoose.Schema

    express.post('/', async (req, res) => {
        // strict false will allow you to save document which is coming from the req.body
        const testCollectionSchema = new Schema({}, { strict: false })
        const TestCollection = mongoose.model('test_collection', testCollectionSchema)
        let body = req.body
        const testCollectionData = new TestCollection(body)
        await testCollectionData.save()
        return res.send({
            "msg": "Data Saved Successfully"
        })
    })


  [1]: https://www.meanstack.site/2020/01/save-data-to-mongodb-without-defining.html

0
你还可以使用mongoose.connection.collection
import mongoose from 'mongoose';

const collection = mongoose.connection.collection('user')

// use it like a mongodb collection
await collection.updateOne({ name: "name" }, { $set: { name: "new_name" } })

查看mongoose文档

0
注意:参数{ strict: false }适用于创建和更新操作。

0
在模型方案中添加{strict: false },并在保存事件中添加{validateBeforeSave: false }
let MyScheme = new Schema(
    { <optional - basic fields if you want> ...},
    {strict: false }
)
let doc = new MyScheme(req.body)
doc.save({validateBeforeSave: false });

-14

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接