Maison  >  Article  >  développement back-end  >  Agrégation, insertion de données d'une collection dans une autre collection

Agrégation, insertion de données d'une collection dans une autre collection

王林
王林avant
2024-02-10 23:30:19727parcourir

Agrégation, insertion de données dune collection dans une autre collection

Dans cet article, l'éditeur PHP Youzi vous présentera une opération courante : l'agrégation, qui consiste à insérer des données d'une collection dans une autre collection. Les opérations d'agrégation sont très courantes en programmation et peuvent être utilisées dans divers scénarios tels que la fusion de données, la déduplication et le filtrage. Grâce aux opérations d'agrégation, nous pouvons facilement traiter et gérer les données, améliorant ainsi l'efficacité et la lisibilité du code. Ensuite, nous présenterons en détail l’utilisation des opérations d’agrégation et les précautions pour aider chacun à mieux maîtriser cette technique.

Contenu de la question

J'essaie de faire ce qui suit pour ajouter le dernier message de la collection chat 集合中获取聊天列表,并将发送的 message d'un utilisateur spécifique à cette liste pour chaque discussion.

Maintenant, comment cela fonctionne, j'ai deux méthodes décrites ci-dessous

Tout d'abord, j'obtiens simplement la liste des discussions en utilisant l'identifiant du membre du chat, la deuxième méthode utilise l'agrégation pour trouver le dernier message de chaque discussion, puis je fais simplement correspondre le message avec l'identifiant du chat

Chat préféré :

type chat struct {
    id           string   `json:"id" bson:"id"`
    participants []string `json:"participants" bson:"participants"`
    lastmessage  *message `json:"last_message,omitempty" bson:"last_message"`
    ...
}

P.S. lastmessage - est toujours zéro, j'en ai seulement besoin pour écrire une réponse pour l'utilisateur.

Collectionmessage :

type message struct {
    id         string `json:"id" bson:"id"`
    chatid     string `json:"chat_id" bson:"chat_id"`
    fromid     string `json:"from_id" bson:"from_id"`
    createdate int64  `json:"create_date" bson:"create_date"`
    body     string `json:"body" bson:"body"`
    updateat int64  `json:"update_at" bson:"update_at"`
    ...
}

Première méthode : J'ai besoin de cette méthode pour obtenir la liste de discussion active d'un participant au chat spécifique.

func activechats(ctx context.context, uid string) ([]*chat, error) {
    ...
    filter := bson.d{primitive.e{key: "participants", value: uid}}
    cursor, err := r.col.find(ctx, filter, nil)
    if err != nil {...}

    var ch []*chat
    if err = cursor.all(ctx, &ch); err != nil {...}

    if err = cursor.close(ctx); err != nil {...}
    ...
}

Deuxième méthode : j'ai besoin de cette méthode pour obtenir le dernier message de chaque discussion, l'entrée est un ensemble d'identifiants de discussion, et pour chaque discussion, je recherche le dernier message, le cas échéant. Pour cela, j'utilise l'agrégation.

func lastmessages(ctx context.context, chatids []string) (map[string]*message, error) {

    matchstage := bson.d{
        primitive.e{
            key: "$match", value: bson.d{
                primitive.e{
                    key: "chat_id", value: bson.d{
                        primitive.e{key: "$in", value: chatids},
                    },
                },
            },
        }}
    sortstage := bson.d{primitive.e{key: "$sort", value: bson.d{primitive.e{key: "created", value: -1}}}}
    groupstage := bson.d{primitive.e{
        key: "$group", value: bson.d{
            primitive.e{
                key: "_id", value: bson.d{
                    primitive.e{key: "chat_id", value: "$chat_id"},
                },
            },
            primitive.e{
                key: "message", value: bson.d{
                    primitive.e{key: "$first", value: "$$root"},
                },
            },
        },
    }}

    cursor, err := r.colmessage.aggregate(ctx, mongo.pipeline{matchstage, groupstage, sortstage})
    if err != nil {...}

    var res []*aggregationresultgenerated
    if err = cursor.all(ctx, &res); err != nil {...}
    ...
}

Je sais que c'est une très mauvaise solution mais c'est tout ce à quoi je pense jusqu'à présent et c'est dommage (ne fonctionne pas). J'essaie de résoudre ce problème

db.chat.aggregate([
    {
        $match: {
            participants: "participant_id",
    },
    {
        $lookup: {
            from: "message", // other table name
            localfield: "id", // name of chat table field
            foreignfield: "chat_id", // name of message table field
            as: "msg",
        }
    },
    {
        $unwind: "$msg",
    },
    {
        $match: {
            chat_id : {
                $in: ["$$root._id"],
            },
        },
    },
    {
        $sort: {
            "created": -1,
        },
    },
    {
        $group: {
            "_id": {
                "chat_id": "$chat_id"
            },
            "doc": {
                "$last": "$$root"
            }
        }
    },
    {
        $project: {
            last_message: "$msg",
        }
    }
])

Ma question est : Comment utiliser l'agrégation pour obtenir une liste de chats pour un utilisateur spécifique et pour chaque chat ajouter le dernier message dans le champ last_message dans l'objet chat de la collection message 集合中添加对象 chat ? Comment ça marche maintenant :

{
    "chats": [
        {
            "id": "4hWsHam3ZZpoyIw44q3D",
            "title": "Chat example",
            "create-date": 1674476855918,
            "participants": [
                "63ce54460aeee5e72c778d90",
                "63ce54460aeee5e72c778d92"
            ],
            "owner_id": "63ce54460aeee5e72c778d90",
            "last_message": {
                "id": "tzwekCiCLSXJ4tfdQuHH",
                "chat_id": "4hWsHam3ZZpoyIw44q3D",
                "from_id": "63ce54460aeee5e72c778d92",
                "create_date": 1674557062031,
                "body": "text",
                "update_at": 0,
                "viewed": false
            },
            "unread": 5
        },
        {
            "id": "Anjrr9RCWFzq030Cwz7S",
            "title": "New chat One",
            "create-date": 1674476909054,
            "participants": [
                "63ce54460aeee5e72c778d90",
                "63ce54460aeee5e72c778d96"
            ],
            "owner_id": "63ce54460aeee5e72c778d90",
            "last_message": {
                "id": "7YqhhS1-EfMRSZtGCH0Z",
                "chat_id": "Anjrr9RCWFzq030Cwz7S",
                "from_id": "63ce54460aeee5e72c778d96",
                "create_date": 1674575017115,
                "body": "text",
                "update_at": 0,
            },
            "unread": 1
        },
    ]
}

Solution de contournement

EDIT : Comme l'OP l'a mentionné dans les commentaires, la mise à jour/$mergede la collection n'est pas nécessaire.

Vous pouvez simplement exécuter la méthode $sort + $limit dans le sous-pipeline de $lookup. Exécutez $unwind pour écrire les résultats de la recherche dans le champ last_message. Enfin, exécutez $lookup 的子管道中执行 $sort + $limit 方法。执行 $unwind 将查找结果写入 last_message 字段。最后,执行 $merge 以更新回 chat pour revenir à la collection chat.

db.chat.aggregate([
  {
    $match: {
      participants: "63ce54460aeee5e72c778d90",
      
    }
  },
  {
    $lookup: {
      from: "message",
      localField: "id",
      foreignField: "chat_id",
      pipeline: [
        {
          $sort: {
            created: -1
          }
        },
        {
          $limit: 1
        }
      ],
      as: "last_message",
      
    }
  },
  {
    $unwind: {
      path: "$last_message",
      preserveNullAndEmptyArrays: true
    }
  },
  {
    $project: {
      last_message: "$last_message"
    }
  }
])

aire de jeux mongo

Voici un ancien terrain de jeu mongo avec $merge mis à jour dans une collection.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer