Tengo una colección dentro de MongoDB (4.4 pero la versión no es importante para mí) y uno de los valores del documento es una matriz de URL. Habrá varios documentos con varias URL por documento (dentro de la matriz) y algunas de esas URL ya existirán. Me gustaría seleccionar cada documento con la primera aparición de cada URL (la intención es marcarlo como el 'origen'.
Enlace de MongoPlayground para la colección de muestras: https://mongoplayground.net/p/ZAgCqr517-8
{ "title": "story1_first", "isoDate": "2022-01-01T00:00:00.000Z", "links": [ "www.first.com/article1", "www.anotherdomain.com" ] }, { "title": "story1_mention", "isoDate": "2022-01-10T00:00:00.000Z", "links": [ "www.first.com/article1", "www.somesite.com" ] }, { "title": "story2_first", "isoDate": "2022-01-20T00:00:00.000Z", "links": [ "www.newstory.com/article2", "www.anothercompany.com" ] }, { "title": "story2_mention", "isoDate": "2022-01-20T00:00:00.000Z", "links": [ "www.newstory.com/article2", "www.anothercompany.com" ] } ]
En este ejemplo, me gustaría que la consulta/agregación devuelva los dos documentos con "primero" en el título, ya que son los documentos que comparten una URL común dentro de los "enlaces" y son los documentos que tienen la fecha más antigua. Similar a cómo un motor de búsqueda clasifica un sitio dependiendo de cuántos otros sitios se vinculan a él.
Puede hacer lo siguiente en una canalización de agregación:
$unwind
links
para que los documentos estén en el nivel de enlaces$sort
on isoDate
para obtener el primer documento$group
por links
para contar entre el grupo y la identificación del primer documento. En su ejemplo, el título se toma como identificador único.$match
con el conteo > 1 para obtener un title
que comparte el mismo enlace$group
para deduplicar el identificador único que encontramos en el paso 3$lookup
nuevo el documento original y hacer algunos cosméticos por $replaceRoot
db.collection.aggregate([ { "$unwind": "$links" }, { $sort: { isoDate: 1 } }, { $group: { _id: "$links", first: { $first: "$title" }, count: { $sum: 1 } } }, { $match: { count: { $gt: 1 } } }, { $group: { _id: "$first" } }, { "$lookup": { "from": "collection", "localField": "_id", "foreignField": "title", "as": "rawDocument" } }, { "$unwind": "$rawDocument" }, { "$replaceRoot": { "newRoot": "$rawDocument" } } ])
Aquí está el parque infantil de Mongo para su referencia.