【问题标题】:How can I perform a find in Mongo (meteor) that finds a document where an array matches? [duplicate]如何在 Mongo(流星)中执行查找以查找数组匹配的文档? [复制]
【发布时间】:2016-02-24 18:12:36
【问题描述】:

我正在尝试在 Meteor 中返回一个光标(使用 MongoDB)。

我正在寻找参与者字段与我传入的数组完全匹配的文档(MessageThreads 集合)。

下面是一个示例 MessageThread 文档

{
  "_id": "YYSELCguhLurTeyNY",
  "creator": "RLmnidY6GypdqDXZu",
  "participants": [
    "SNhRq4vQpwFBjnTSH",
    "RLmnidY6GypdqDXZu"
  ],
}

当我执行 addMessage 方法时,我首先尝试检查是否存在participants 与我传入的数组完全匹配的线程。该数组将根据新消息表单tofield 制定。

因此,只有当我的所有 participants 数组都在文档 participants 字段内但没有其他字段时,才应返回文档。例如:如果文档中存在不属于新消息to 字段的第三人,则不应返回该文档。

目前这是我的查询,显然太简单了。

existingThread = MessageThreads.findOne(participants: participants)

有什么建议吗?谢谢

编辑:我在使用提供的重复答案时遇到问题(但还不允许评论其他线程)

由于某种原因,如果数组不同,existingThread 仍在查找文档,但 size 为真。

编辑 2:

下面是我的整个方法的代码,它可以帮助破译我哪里出错了。在咖啡脚本中(请原谅标签,无法让它在 SO 中工作,抱歉)。

Meteor.methods

newMessage: (recipientIds, messageContent) ->

if !Meteor.userId()
  return false

userId = Meteor.userId()

check recipientIds, [String]
check messageContent, String

participants = recipientIds
participants.push(userId)
participantCount = _.size(participants)

existingThread = MessageThreads.findOne participants:
  $size: participantCount
  $in: participants

if existingThread?
  console.log "Thread exists: #{existingThread._id}"

  MessageThreads.update existingThread,
    $addToSet: messages: {sender: userId, content: messageContent}
    $set: lastUpdated: new Date()


else
  newThreadId = MessageThreads.insert 
    creator: userId
    participants: participants
    messages: [
      {
        sender: userId
        content: messageContent
        createdAt: new Date()
      }
    ]
    lastUpdated: new Date()

  return newThreadId

【问题讨论】:

  • 从谷歌搜索mongodb array exact match开始。这揭示了许多有用的答案。
  • 非常感谢,您是对的,我显然搜索效率不高!这个 SO question 似乎有一个这样的答案。 stackoverflow.com/questions/29774032/…
  • :P 很好的发现,忘记了这个答案可以很好地适用于你的情况。
  • 没看到也是你的回答谢谢!
  • 事实证明,将 $all 与 $size 结合起来似乎可以解决问题。

标签: arrays mongodb meteor


【解决方案1】:

您需要在查询中使用 $all 运算符来选择字段值是包含所有指定元素的数组的文档。当你想返回一个游标时,find() 方法更合适,因为它返回一个游标。它不会立即访问数据库或返回文档。要访问游标中的文档,游标提供fetch()返回所有匹配的文档,map()forEach()遍历所有匹配的文档,observe()observeChanges()在匹配文档集更改时注册回调.

对于您的情况,示例实现如下所示:

var existingThreadsCursor = MessageThreads.find({ "participants": { "$all": participants} });
var count = 0;
existingThreadsCursor.forEach(function (thread){
    console.log("Thread with participants: " + JSON.stringify(thread.participants));
    count++;
});

【讨论】:

  • 非常感谢!当我说我想返回一个游标时,我认为我是在误导,我认为findOne 很好,因为我真的想知道这样的线程是否存在。如果我只想要一个完全匹配的 $all 仍然可以工作吗?我认为如果它找到了我的数组中的所有项目,但如果其他项目也在其中,它仍然可以工作?
  • 是的,它仍然可以工作,因为它匹配字段包含指定数组元素的文档。因此,findOne$all 一起将返回单个文档,如果它具有完全匹配的数组,否则返回 null。
  • 谢谢,我认为我遇到了 $all 的问题,如果数组的顺序不同,则不匹配。
  • 好吧,在这种情况下,我在stackoverflow.com/a/29774404/122005 提供的答案对你有用。
  • 谢谢,它的大小或名称都可能匹配吗?看起来如果它找到一个参与者数量相同的线程,它就会把消息放在那里?
猜你喜欢
  • 1970-01-01
  • 2016-07-27
  • 1970-01-01
  • 2020-09-06
  • 2015-05-23
  • 2020-06-01
  • 2019-01-10
  • 1970-01-01
  • 2019-07-16
相关资源
最近更新 更多