mongodb检查从一个集合到其他集合中所有字段的字段的正则表达式

mongodb检查从一个集合到其他集合中所有字段的字段的正则表达式,mongodb,mongoose,Mongodb,Mongoose,挖了谷歌等一个星期后,我终于在这里问了这个问题。假设有两个集合 用户集合: [ {... name:"James" userregex: "a|regex|str|here" }, {... name:"James" userregex: "another|regex|string|there" }, ... ] [ {... title:"a string here ..." }, {... title: "another string her

挖了谷歌等一个星期后,我终于在这里问了这个问题。假设有两个集合

用户集合:

[
{...
    name:"James"
    userregex: "a|regex|str|here"
},
{...
    name:"James"
    userregex: "another|regex|string|there"
},
...
]
[
{...
    title:"a string here ..."
},
{...
    title: "another string here ..."
},
...
]
收集后:

[
{...
    name:"James"
    userregex: "a|regex|str|here"
},
{...
    name:"James"
    userregex: "another|regex|string|there"
},
...
]
[
{...
    title:"a string here ..."
},
{...
    title: "another string here ..."
},
...
]
我需要获取其
userregex
将匹配任何
post.title
(需要用户id、post\u id组或类似内容)的所有用户

到目前为止我所尝试的:
1.获取集合中的所有用户,在所有产品上运行regex,工作正常,但太脏了!它必须为每个用户执行一个查询 2.与上面相同,但在Mongo查询中使用foreach,与上面相同,只是数据库层而不是应用层

我搜索了很多可用的方法,如聚合、逆风等,但运气不佳。

那么在Mongo有可能做到这一点吗?我应该更改我的数据库类型吗?如果是的话,哪种类型比较好?性能是我的首要任务。谢谢

MongoDB适合您的用例,但您需要使用与当前不同的方法。由于您只关心与任何帖子匹配的任何标题,因此可以存储此类匹配的最后结果。下面是一个示例代码

db.users.find({last_post_id: {$exists: 0}}).forEach(
   function(row) {
       var regex = new RegExp(row['userregex']);
       var found = db.post_collection.findOne({title: regex});
       if (found) {
           post_id = found["post_id"];
           db.users.updateOne({
                 user_id: row["user_id"]
               }, {
                    $set :{ last_post_id:  post_id}
                   }); 
       }
   }
)
它的作用是只过滤没有设置
last\u post\u id
的用户,搜索post记录以查找该用户,并在找到记录时设置
last\u post\u id
。所以在运行这个之后,您可以返回如下结果

db.users.find({last_post_id: {$exists: 1}}, {user_id:1, last_post_id:1, _id:0})
你唯一需要关心的是对现有帖子的编辑/删除。因此,在每次编辑/删除之后,您应该只运行下面的命令,以便再次运行该帖子id的所有匹配项

post_id_changed = 1
db.users.updateMany({last_post_id: post_id_changed}, {$unset: {last_post_id: 1}})
这将确保下次运行更新时再次处理这些用户。这种方法确实有一个缺点,即对于没有匹配标题的每个用户,对这些用户的查询都会一次又一次地运行。尽管您可以通过使用一些时间戳或后期计数检查来解决这个问题


此外,您还应该确保将索引放在
post\u collection.title

上,我想如果您像这样预先标记您的帖子标题:

{
  "_id": ...
  "title": "Another string there",
  "keywords": [
    "another",
    "string",
    "there"
  ]
}
但不幸的是,foreignField是一个单独的元素,所以我的想法不会奏效:(但也许它会给你另一个想法

db.Post.aggregate([
   {$lookup: {
          from: "Users",
          localField: "keywords",
          foreignField: "keywords",
          as: "users"
        }
    },
]))

无法在匹配表达式内的正则表达式运算符中引用文档中存储的正则表达式字段

因此,目前的结构无法在mongo端实现

$lookup
适用于相等条件。因此,一种替代方法(类似于Nic建议的方法)是更新您的帖子集,为每个标题添加一个名为
关键字的额外字段(可搜索的关键字值数组)

db.users.aggregate([
   {$lookup: {
          from: "posts",
          localField: "userregex",
          foreignField: "keywords",
          as: "posts"
        }
    }
])
上面的查询将执行类似的操作(从3.4开始)

从文件中

如果该字段包含数组,则$in运算符将选择 其字段包含至少包含一个数组的文档 与指定数组中的值匹配的元素(例如, (等)

看起来只有当数组的顺序、值和长度相同时,早期版本(在3.2上测试)才会匹配

样本输入:

使用者

职位

样本输出:

[
  {
    "name": "James",
    "userregex": [
      "another",
      "here"
    ],
    "posts": [
      {
        "title": "another string here",
        "keywords": [
          "another",
          "here"
        ]
      },
      {
        "title": "a string here",
        "keywords": [
          "here"
        ]
      }
    ]
  },
  {
    "name": "John",
    "userregex": [
      "another",
      "string"
    ],
    "posts": [
      {
        "title": "another string here",
        "keywords": [
          "another",
          "here"
        ]
      },
      {
        "title": "one string here",
        "keywords": [
          "string"
        ]
      }
    ]
  }
]

由于这似乎是您不需要为特定用户执行的操作,因此可能需要执行昂贵的计算(您无论如何都无法四处走动)并将结果缓存在内存中。听起来这可能是AB问题。@IngoBürk我无法缓存结果,新数据在PostCollection中出现,UsersCollection get也更新了。可能使用一些标志处理新的\changed文档,但太脏了添加帖子不会更改缓存结果。只有删除它们才会更改缓存结果,而且你可以通过记忆与某个用户匹配的帖子(如果是删除的帖子,请为受影响的用户重新计算)和添加用户来解释。你只需计算单个用户的信息并将其添加到缓存中。你做了类似的事情,对吗?你的正则表达式都只是管道“或”如果是这样的话,您可以将它们存储在一个数组中,并使用聚合框架进行$lookup。
[
  {
    "name": "James",
    "userregex": [
      "another",
      "here"
    ],
    "posts": [
      {
        "title": "another string here",
        "keywords": [
          "another",
          "here"
        ]
      },
      {
        "title": "a string here",
        "keywords": [
          "here"
        ]
      }
    ]
  },
  {
    "name": "John",
    "userregex": [
      "another",
      "string"
    ],
    "posts": [
      {
        "title": "another string here",
        "keywords": [
          "another",
          "here"
        ]
      },
      {
        "title": "one string here",
        "keywords": [
          "string"
        ]
      }
    ]
  }
]