Heim  >  Artikel  >  Backend-Entwicklung  >  Aggregation, Einfügen von Daten aus einer Sammlung in eine andere Sammlung

Aggregation, Einfügen von Daten aus einer Sammlung in eine andere Sammlung

王林
王林nach vorne
2024-02-10 23:30:19725Durchsuche

Aggregation, Einfügen von Daten aus einer Sammlung in eine andere Sammlung

In diesem Artikel stellt Ihnen der PHP-Editor Youzi eine gängige Operation vor – die Aggregation, bei der Daten aus einer Sammlung in eine andere Sammlung eingefügt werden. Aggregationsvorgänge sind in der Programmierung weit verbreitet und können in verschiedenen Szenarien wie dem Zusammenführen von Daten, der Deduplizierung und dem Filtern verwendet werden. Durch Aggregationsvorgänge können wir Daten einfach verarbeiten und verwalten und so die Effizienz und Lesbarkeit des Codes verbessern. Als nächstes werden wir die Verwendung von Aggregationsoperationen und Vorsichtsmaßnahmen im Detail vorstellen, um allen zu helfen, diese Technik besser zu beherrschen.

Frageninhalt

Ich versuche Folgendes zu tun, um für jeden Chat die letzte Nachricht aus der chat 集合中获取聊天列表,并将发送的 message-Sammlung eines bestimmten Benutzers zu dieser Liste hinzuzufügen.

Wie das funktioniert, habe ich zwei Methoden, wie unten beschrieben

Zuerst erhalte ich einfach die Liste der Chats mithilfe der Chat-Mitglieder-ID, die zweite Methode verwendet Aggregation, um die letzte Nachricht jedes Chats zu finden, und dann ordne ich einfach die Nachricht der Chat-ID zu

Lieblingschat:

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 - ist immer Null, ich brauche es nur, um eine Antwort für den Benutzer zu schreiben.

Sammlungmessage:

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"`
    ...
}

Erste Methode: Ich benötige diese Methode, um die aktive Chat-Liste eines bestimmten Chat-Teilnehmers abzurufen.

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 {...}
    ...
}

Zweite Methode: Ich benötige diese Methode, um die letzte Nachricht jedes Chats abzurufen. Die Eingabe besteht aus einer Reihe von Chat-IDs, und für jeden Chat suche ich nach der letzten Nachricht, falls vorhanden. Dazu verwende ich Aggregation.

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 {...}
    ...
}

Ich weiß, das ist eine wirklich schlechte Lösung, aber das ist alles, was mir bisher einfällt, und es ist sehr traurig (funktioniert nicht). Ich versuche dieses Problem zu lösen

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",
        }
    }
])

Meine Frage ist: Wie verwende ich die Aggregation, um eine Liste von Chats für einen bestimmten Benutzer zu erhalten und für jeden Chat die letzte Nachricht im Feld last_message im Objekt chat aus der message 集合中添加对象 chat-Sammlung hinzuzufügen? So funktioniert es jetzt:

{
    "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
        },
    ]
}

Workaround

EDIT: Wie im OP in den Kommentaren erwähnt, ist eine Aktualisierung/$mergeder Sammlung nicht erforderlich.

Sie können einfach die Methode $sort + $limit in der Subpipeline von $lookup ausführen. Führen Sie $unwind aus, um die Suchergebnisse in das Feld last_message zu schreiben. Führen Sie abschließend $lookup 的子管道中执行 $sort + $limit 方法。执行 $unwind 将查找结果写入 last_message 字段。最后,执行 $merge 以更新回 chat aus, um wieder auf die chat-Sammlung zu aktualisieren.

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"
    }
  }
])

Mongo-Spielplatz

Hier ist ein alter Mongo-Spielplatz mit $merge, der zu einer Sammlung aktualisiert wurde.

Das obige ist der detaillierte Inhalt vonAggregation, Einfügen von Daten aus einer Sammlung in eine andere Sammlung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen