MongoDB: отличительные значения от объектов в подмассиве - PullRequest
1 голос
/ 13 мая 2019

У меня есть коллекция документов, структурированная следующим образом. Например:

{ 'observer': 'machine1', 
  'seen': [ 
     {'page1': ['/link1', '/link3']},
     {'page2': ['/link4', '/link1']},
}

{ 'observer': 'machine2', 
  'seen': [ 
     {'page3': ['/link2']},
     {'page1': ['/link5']},
}

Я пытаюсь получить список всех различных ключей и значений в массиве, сгруппированных по observer. В идеальном мире это будет выглядеть примерно так:

{'machine1': ['/link1', '/link3', '/link4'], 'machine2': ['/link2', '/link5'] }

и

{'machine1': ['page1', 'page2'], 'machine2': ['page1', 'page3']}

Я понимаю, что могу использовать $ aggregate и $ group для получения уникальных значений, основанных на подсписках, но я не уверен, как обращаться со списками объектов и захватывать их ключи и значения.

1 Ответ

1 голос
/ 13 мая 2019

Вы можете использовать ниже агрегации

db.collection.aggregate([
  { "$unwind": "$seen" },
  { "$addFields": {
    "seen": {
      "$objectToArray": "$seen"
    }
  }},
  { "$unwind": "$seen" },
  { "$unwind": "$seen.v" },
  { "$group": {
    "_id": "$observer",
    "links": { "$addToSet": "$seen.v" }
  }}
])

MongoPlayground

Если вам нужно pages и links одновременно

db.collection.aggregate([
  { "$unwind": "$seen" },
  { "$addFields": {
    "seen": {
      "$objectToArray": "$seen"
    }
  }},
  { "$unwind": "$seen" },
  { "$unwind": "$seen.v" },
  { "$facet": {
    "pages": [
      { "$group": {
        "_id": "$observer",
        "pages": { "$addToSet": "$seen.v" }
      }}
    ],
    "links": [
      { "$group": {
        "_id": "$observer",
        "links": { "$addToSet": "$seen.k" }
      }}
    ]
  }}
])

MongoPlayground

Если вам нужно дополнительное улучшение

db.collection.aggregate([
  { "$unwind": "$seen" },
  { "$addFields": {
    "seen": {
      "$objectToArray": "$seen"
    }
  }},
  { "$unwind": "$seen" },
  { "$unwind": "$seen.v" },
  { "$facet": {
    "pages": [
      { "$group": {
        "_id": "$observer",
        "pages": { "$addToSet": "$seen.v" }
      }}
    ],
    "links": [
      { "$group": {
        "_id": "$observer",
        "pages": { "$addToSet": "$seen.k" }
      }}
    ]
  }},
  { "$project": {
    "pages": {
      "$map": {
        "input": "$pages",
        "in": {
          "$let": {
            "vars": {
              "links": {
                "$arrayElemAt": [
                  "$links",
                  { "$indexOfArray": ["$links._id", "$$this._id"] }
                ]
              }
            },
            "in": {
              "_id": "$$this._id",
              "pages": "$$this.pages",
              "links": "$$links.links"
            }
          }
        }
      }
    }
  }},
  { "$unwind": "$pages" },
  { "$replaceRoot": { "newRoot": "$pages" }}
])

MongoPlayground

...