Node.js MongoDB按非索引字段排序的最佳实践
我有一个应用程序,允许用户使用自己的自定义数据,所以我不知道数据是什么。但是,我确实希望允许他们对数据进行排序。 这可能是大量的数据,mongodb最终给了我内存错误(32MB限制)Node.js MongoDB按非索引字段排序的最佳实践,node.js,mongodb,sorting,meteor,Node.js,Mongodb,Sorting,Meteor,我有一个应用程序,允许用户使用自己的自定义数据,所以我不知道数据是什么。但是,我确实希望允许他们对数据进行排序。 这可能是大量的数据,mongodb最终给了我内存错误(32MB限制) 最好的方法是什么?如何允许用户按未知字段对大量数据进行排序 MongoDB允许您以这样一种方式设计模式:它可以在模式中存储对象和对象关系,因此您可以允许用户存储任何类型的信息。正如@kevinadi所说,有32MB的限制。就排序而言,它可以在服务器端完成 这是我在MongoDB和Mongoose ORM中存储对象时
最好的方法是什么?如何允许用户按未知字段对大量数据进行排序 MongoDB允许您以这样一种方式设计模式:它可以在模式中存储对象和对象关系,因此您可以允许用户存储任何类型的信息。正如@kevinadi所说,有32MB的限制。就排序而言,它可以在服务器端完成 这是我在MongoDB和Mongoose ORM中存储对象时尝试的一个示例
var mongoose = require("mongoose");
var userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true,
lowercase: true,
trim: true,
match: [/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/, "Please fill a valid email address"]
},
custInfo:{
type:Object,
required: true
}
isConfirmed: {
type: Boolean,
required: true,
default: false
},
confirmedOn:{
type: Date,
required: true,
default: Date.now()
}
});
module.exports = mongoose.model("user",userSchema);
既然您已经标记了这个问题Meteor,我想您就有了默认的Meteor环境,在这里您可以使用客户端轻量级 这使您有机会发布(发布)/返回(方法)大部分未排序的数据,并让客户机处理此任务 试想一下:只有100个客户端要求发布一个每次排序操作都会更新的发布(因为订阅参数会更改,所以发布也会更改) 这已经导致服务器消耗大量RAM,以使观察器(OPLOG等)运行100个发布,每个发布查询大量文档 可能的性能解决方案如下所述。请记住,它们不受任何前端的约束,而是一个概念描述。根据您的前端环境,您必须包括反应性等 选项A-未排序发布,让客户端排序 服务器 客户
const handle=Meteor.subscribe('hugeData'))
if(handle.ready()){
const sortedData=MyCollection.find({…},{sort:{someField:-1})
}
这里有一个很大的优点,如果使用,您可以通知客户完整性状态
请注意,如果要向后扫描(返回文档,使用最新文档),可以使用提示
:
Meteor.publish('hugeData',函数(){
返回MyCollection.find({…},{提示:{$natural:-1})
})
这比{sort:{fieldName:-1}}
更有效
选项B-返回未排序的from方法,让客户端排序
现在解决方案a可能仍然存在问题,因为如果有很多订户,它仍然需要消耗大量的RAM。另一种选择(特别是如果实时数据更改不那么相关)是使用Meteor方法:
服务器
Meteor.method('hugeData',函数(){
返回MyCollection.find({…}).fetch()
})
请注意,这需要向文档发送消息,否则将抛出未处理的PromiserRejection
客户
这需要客户端上的LocalCollection
,即与服务器端集合不同步,否则将出现文档同步问题:
const HugeData=new LocalCollection(null)//注意null作为集合名称!
const insertUpdate=文档=>{
if(LocalCollection.findOne(document.\u id)){
删除文档。\u id
返回LocalCollection.update(document.\u id,document)
}否则{
返回LocalCollection.insert(文档)
}
}
Meteor.call('hudeData',(错误,数据)=>{
数据。forEach(插入更新)
})
然后,您可以在客户端上使用LocalCollection
对接收到的数据进行任何投影
总而言之,将负载移动到客户端是一个很好的折衷办法。只要您在投影需要一段时间时通知他们,就应该可以了。我目前的想法是添加一个包含1.entity id、2个字段名称和3.field value的索引集合。
将该集合编入索引,然后从中提取有序的实体ID,稍后按ID加载完整的相关文档。没有关于无索引排序的最佳实践。内存排序在MongoDB端限制为32MB的RAM,因此我可以想到两个备选方案:1)在应用程序中进行排序,2)设计模式,以便t你可以有一个可以排序的索引。否则,32MB的限制最终会影响你。@kevinadi有没有关于DB设计的想法?谢谢你的回答,但似乎客户在大约2000条记录之后不知所措(这是在一台强大的机器上)。是否
被淹没
意味着内存、文档异步移位、cpu峰值或冻结?速度太慢了
Meteor.publish('hugeData', function () {
return MyCollection.find({ ...})
})