我有一个“用户”和“聊天”集合
用户方案类似于:
username: {
type: String,
unique: true, required: true
}
聊天方案:
from: {
type: Schema.Types.ObjectId,
required: true
},
to:{
type: Schema.Types.ObjectId,
required: true
},
content:{
type:String,
required:true
}
我的目的是在一个用户和另一个随机选择的用户之间开始聊天。
到目前为止,我的代码可以选择随机用户:
User.aggregate([
{ "$match": { "_id": { "$ne": mongoose.Types.ObjectId(from_id) }}},
{$sample: {size: 1}}]
我正在使用"$ne": mongoose.Types.ObjectId(from_id)
,因此不会选择同一用户。
我想要实现的是选择一个用户,除了同一个用户(完成)之外,还选择了第一个用户已经与之聊天的人。 就像如果user1和user2之间已经存在聊天,那么代码必须选择除user2之外的另一个用户。
答案 0 :(得分:1)
替代您的方法:
main
在聊天集合中使用诸如(const count = model.estimatedDocumentCount()
if (count === 2) {
throe new Error('Not possible')
}
let newUser = null
let i = 0
while(true) {
const random = Math.random() * count
newUser = await model.findOne({_id: {$ne: fromId}}).skip(random).exec()
if (!(await chatModel.findOne({$or: [{from: fromId, to: newUser._id}, {to: fromId, from: newUser._id}]}, {_id: 1}).exec())) {
break
}
if (i === 1000) {
throw new Error('Ah well not today') // can come up with some alternative strategy
}
++i
}
)之类的复合索引。
应该对大型集合(因为命中相同的可能性较低)以及小型集合都可以很好地工作,因为集合应该适合内存并且易于从磁盘读取。