Группировать по элементу массива в Mongodb

#mongodb #aggregation-framework

#mongodb #структура агрегации

Вопрос:

У нас есть вложенный документ и мы пытаемся сгруппировать по элементу массива. Наша структура документа выглядит следующим образом

 /* 1 */
{
    "_id" : ObjectId("5a690a4287e0e50010af1432"),
    "slug" : [ 
        "true-crime-the-10-most-infamous-american-murder-mysteries", 
        "10-most-infamous-american-murder-mysteries"
    ],
    "tags" : [ 
        {
            "id" : "59244aa6b1be5055278e9b5b",
            "name" : "true crime",
            "_id" : "59244aa6b1be5055278e9b5b"
        }, 
        {
            "id" : "5924524db1be5055278ebd6e",
            "name" : "Occult Museum",
            "_id" : "5924524db1be5055278ebd6e"
        }, 
        {
            "id" : "5a690f0fc1a72100110c2656",
            "_id" : "5a690f0fc1a72100110c2656",
            "name" : "murder mysteries"
        }, 
        {
            "id" : "59244d71b1be5055278ea654",
            "name" : "unsolved murders",
            "_id" : "59244d71b1be5055278ea654"
        }
    ]
}  

Мы хотим найти список всех групп слизней по имени тега. Я пытаюсь следовать, и он получает результат, но он неточный. У нас есть сотни записей с каждым тегом, но я получаю только несколько с моим запросом. Я не уверен, что я здесь делаю не так.
Заранее спасибо.

 // Requires official MongoShell 3.6 

db.getCollection("test").aggregate(
    [
        { 
            "$match" : {
                "item_type" : "Post", 
                "site_id" : NumberLong(2), 
                "status" : NumberLong(1)
            }
        },
		{$unwind: "$tags" },         
        { 
            "$group" : {
                "_id" : {
                    "tags᎐name" : "$tags.name",
                    "slug" : "$slug"
                }
            }
        }, 
        { 
            "$project" : {
                "tags.name" : "$_id.tags᎐name",
                "slug" : "$_id.slug",
                "_id" : NumberInt(0)
            }
        }
    ], 
    { 
        "allowDiskUse" : true
    }
);  

Ожидаемый результат

 TagName     Slug
----------
true crime "true-crime-the-10-most-infamous-american-murder-mysteries", 
           "10-most-infamous-american-murder-mysteries"
           "All records where tags true crime"
  

Комментарии:

1. можете ли вы обновить вопрос ожидаемым результатом запроса, который вы хотите?

Ответ №1:

Вместо того, чтобы использовать slug как часть _id , вы должны использовать $ push или $ addToSet для их накопления, попробуйте:

 db.test.aggregate([
    {
        $unwind: "$tags"
    },
    {
        $unwind: "$slug"
    },
    {
        $group: {
            _id: "$tags.name",
            slugs: { $addToSet: "$slug" }
        }
    },
    {
        $project: {
            _id: 1,
            slugs: {
                $reduce: {
                    input: "$slugs",
                    initialValue: "",
                    in: {
                        $concat: [ "$$value", ",", "$$this" ]
                    }
                }
            }
        }
    }
])
  

РЕДАКТИРОВАТЬ: чтобы получить строку, разделенную запятыми, для слизней, вы можете использовать $reduce с $concat

Вывод:

 { "_id" : "murder mysteries", "slugs" : ",10-most-infamous-american-murder-mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
{ "_id" : "Occult Museum", "slugs" : ",10-most-infamous-american-murder-mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
{ "_id" : "unsolved murders", "slugs" : ",10-most-infamous-american-murder-mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
{ "_id" : "true crime", "slugs" : ",10-most-infamous-american-murder- mysteries,true-crime-the-10-most-infamous-american-murder-mysteries" }
  

Комментарии:

1. Это почти то, что мне нужно. Есть ли способ использовать slug в виде строки, разделенной запятой, а не массива? Мне нужно экспортировать эти данные в Excel, и это создает ненужные пустые столбцы

2. @jvm изменил мой ответ