MongoDB高级计数查询,取决于文档的内容

时间:2012-10-05 15:58:25

标签: mongodb count mapreduce nosql

我遇到了使用MongoDB进行高级计数查询的问题。

我想在文档字段中计算 内的对象,但前提是存在与查询匹配的前一个元素且 较旧

让我解释....

我有一个容器文档,看起来像:

{
 "_id" : ...,
 [...]
 "objects" : [ ]
}

在对象字段内:
我有对象文档看起来像:

[
  {
    "_id" : ...,
    "name" : "foo",
    "properties" = [ ],
    "time" = 000000042
  }

  {
    "_id" : ...,
    "name" : "bar",
    "properties" = [ ],
    "time" = 000000424
  }

  {
    "_id" : ...,
    "name" : "baz",
    "properties" = [ ],
    "time" = 000004242
  }

现在我算一下容器文件包含多少:
具有对象1(foo),
的容器的 计数 带有对象1和2(foo和bar)的容器的 计数

对象1,2和3(foo,bar,baz)的容器的 计数

但是现在我想只计算 bar foo (使用时间字段)时才计算foo和bar ... <登记/> 具有对象1(foo),
的容器的 计数 具有对象1和2(foo和bar)的容器的 计数 AND foo.time&lt; bar.time
具有对象1,2和3的容器的 count (foo,bar,baz) AND foo.time&lt; bar.time&lt; baz.time

问题是需要为每个容器更改时间字段。 换句话说:我如何使用每个文档的动态查询

这里是代码示例:

foreach ($COUNTER[ARRAY_FIELDS_NAME_TO_COUNT] as $key => $value)
{
// Build the query (Name & properties)
$match[$key] = array('$elemMatch' => array('name' => $value['name']));
foreach ($value['properties'] as $propertyName => $propertyValue)
  $match[$key]['$elemMatch']["properties.$propertyName"] = $propertyValue;

// Time checking
if ($key > 0)
{
  //FIXME with a... dynamics query searching inside current doc??
  //           or   a special var set to the previous object matched...  or MapReduce..
}


// Make the query
$query = array('objects' => array('$all' => $match));

$result[$key]['count'] = $db->person->count($query);
}

我是MongoDB的新手,我真的不知道有效实现这一目标的最佳做法是什么!

问候!

1 个答案:

答案 0 :(得分:1)

以下是在shell(javascript)中使用Aggregation Framework执行此操作的方法。

请注意,为了便于阅读,我将其拆分为多行,实际查询是最后一行。我曾经使用过foo bar和baz但当然你想调整到更合适的东西。

match = { "$match" : { "objects.name" : "foo" } };
unwind = { "$unwind" : "$objects" };
projectDates = {"$project" : {
        "_id" : 1,
        "objects" : 1,
        "fooDate" : {
            "$cond" : [
                {
                    "$eq" : [
                        "$objects.name",
                        "foo"
                    ]
                },
                "$objects.time",
                0
            ]
        },
        "barDate" : {
            "$cond" : [
                {
                    "$eq" : [
                        "$objects.name",
                        "bar"
                    ]
                },
                "$objects.time",
                0
            ]
        },
        "bazDate" : {
            "$cond" : [
                {
                    "$eq" : [
                        "$objects.name",
                        "baz"
                    ]
                },
                "$objects.time",
                0
            ]
        }
    }
};
group = {"$group" : {
        "_id" : "$_id",
        "objects" : {
            "$push" : "$objects"
        },
        "maxFooDate" : {
            "$max" : "$fooDate"
        },
        "maxBarDate" : {
            "$max" : "$barDate"
        },
        "maxBazDate" : {
            "$max" : "$bazDate"
        }
    }
};
projectCount = {"$project" : {
        "_id" : 1,
        "foos" : {
            "$add" : [
                1,
                0
            ]
        },
        "foosAndBars" : {
            "$cond" : [
                {
                    "$lt" : [
                        "$maxFooDate",
                        "$maxBarDate"
                    ]
                },
                1,
                0
            ]
        },
        "foosBarsAndBazs" : {
            "$cond" : [
                {
                    "$and" : [
                        {
                            "$lt" : [
                                "$maxBarDate",
                                "$maxBazDate"
                            ]
                        },
                        {
                            "$lt" : [
                                "$maxFooDate",
                                "$maxBarDate"
                            ]
                        }
                    ]
                },
                1,
                0
            ]
        }
    }
};
countFoos = {"$group" : {
        "_id" : "FoosBarsBazs",
        "Foos" : {
            "$sum" : "$foos"
        },
        "FBs" : {
            "$sum" : "$foosAndBars"
        },
        "FBBs" : {
            "$sum" : "$foosBarsAndBazs"
        }
    }
};


db.collection.aggregate([match, unwind, projectDates, projectCount, countFoos]).result