Maison > développement back-end > Golang > le corps du texte

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

王林
Libérer: 2024-02-10 23:30:19
avant
691 Les gens l'ont consulté

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"`
    ...
}
Copier après la connexion

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"`
    ...
}
Copier après la connexion

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 {...}
    ...
}
Copier après la connexion

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 {...}
    ...
}
Copier après la connexion

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",
        }
    }
])
Copier après la connexion

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
        },
    ]
}
Copier après la connexion

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"
    }
  }
])
Copier après la connexion

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!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!