MongoDB聚合 $project

6

我把我们的Web服务器日志存储在MongoDB中,模式看起来类似于以下内容:

[
  {  
    "_id" : 12345,
    "url" : "http://www.mydomain.com/xyz/abc.html",
    ....
  },
  ....
]

我正在尝试使用$project操作符,在将我的集合通过聚合管道之前,对此模式进行一些重塑。基本上,我需要添加一个名为"type"的新字段,该字段稍后将用于执行分组操作。新字段的逻辑非常简单。

if "url" contains "pattern_A" then set "type" = "sales lead";
else if "url" contains "pattern_B" then set "type" = "existing client";
...

我认为它可能是这样的:

db.weblog.aggregate(
  { 
    $project : {
      type : { /* how to implement the logic??? */ }
    }
  }
);

我知道如何使用map-reduce完成此操作(通过将“keyf”属性设置为实现上述逻辑的自定义JS函数),但现在正在尝试使用新的聚合框架来完成此操作。我尝试使用表达式运算符来实现该逻辑,但到目前为止还没有成功。非常感谢任何帮助/建议!
2个回答

1

我在这里分享我的“解决方案”,以防其他人遇到与我相同的需求。

经过几周的研究,正如@asya-kamsky在他的评论中建议的那样,我决定向我的原始MongoDB模式添加一个计算字段。虽然这并不理想,因为每当计算字段的逻辑发生变化时,我都需要进行批量更新以更新集合中的所有文档,但这要么是这样,要么就要重写我的代码以使用MapReduce。目前我选择了前者。通过查看MongoDB Jira面板,似乎有很多人要求为$project运算符添加更多不同的运算符,我真诚地希望MongoDB开发团队能尽快添加它们。

基于分隔符拆分字符串的运算符。

新的投影运算符$elemMatch

允许在$project中使用$slice运算符

在 $project 中添加一个 $inOrder 运算符


0

您需要使用多个运算符和表达式的组合。

首先,在$project中使用$cond运算符可以让您实现if-then-else逻辑。

$cond:接受一个由三个元素组成的数组,第一个是布尔表达式,第二个和第三个是用于字段值的值 - 如果布尔表达式为true,则使用第二个元素作为值,否则使用第三个元素。

您可以嵌套这些,以便第三个元素本身是一个$cond表达式,以获取if-then-else-if-then-etc。

字符串操作有点棘手,但您确实可以使用$substr

如果您发布一些关于您尝试的具体示例,我可能能够发现为什么它没有起作用。


谢谢您的回复。你的建议是我尝试的第一件事,但很快就遇到了死胡同,因为我意识到我无法使用支持的字符串操作符检查字符串模式的存在。我需要像indexOf()这样的函数来查找URL中的特定模式。 - Edenbauer
子字符串可以出现在“url”中的哪里?这是在您最初编写文档时存储的可行内容吗? - Asya Kamsky
我遇到了类似的情况。我有两个字段A和B,它们在文档中的存在是相互排斥的。当A存在时,我必须按A分组,当B存在时,则按B分组,但似乎您不能在$project中使用$cond...我尝试以两种方式编写$project: {$project: {MyKey: {$cond: [{$exists: ["$A", true]}, "$A", "$B"]}}} 和 {$project: {MyKey: {$cond: [{"A": {$exists:true}}, "$A", "$B"]}}}但我一直得到错误提示:{ "errmsg" : "exception: invalid operator '$exists'", "code" : 15999, "ok" : 0 } ...也许这只是一个麻烦的语法问题 :( - Aafreen Sheikh
@AafreenSheikh,你所描述的是可行的 - 你可能想要提出另一个问题来解决你的问题,而不是试图在评论中解释。 - Asya Kamsky
@AsyaKamsky 在这里提问:https://dev59.com/emYq5IYBdhLWcg3wxTWq - Aafreen Sheikh

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