Hướng dẫn lookup trong mongodb

Yêu cầu thg 7 31, 2018 7:31 SA 4215 0 0

Show

    Chào mọi người. Mình có 1 app đang làm sử dụng mongodb. Do mới tiếp xúc nên có vấn đề mình gặp phải cần mọi người trợ giúp.

    Mình có 3 model liên quan cụ thể các field phía dưới. Từ Model Review, mình muốn lấy toàn bộ reviews của Book. router api dạng: domain/book_id/reviews. Mỗi review sẽ có comments nên get luôn các comment của review tương ứng( và info tác giả của comment đó). Trong từng comment có trường user_id. Ở đây mình dùng các table riêng biệt.

    Lúc trước minh dùng foEarch lấy ra từng ID rồi truy vấn để lấy thông tin. Nhưng thấy nó Load mất thời gian. Sau đó thì tìm hiểu đc cái lookup và populate này.

    Mình dùng câu truy vấn như này ở Model review.

    async testLookup(book_id, limit, page){
    return await Review.aggregate([
    		{ $match: { "book_id": new mongoose.Types.ObjectId(book_id)} },
            { $lookup: {
                from: 'comments',
                localField: '_id',
                foreignField: 'review_id',
                as: 'comments'
            }},
       ]);
    } 
    

    Kết quả sẽ ra được như thế này. Mình muốn là ở cái user_id sẽ hiển thị Object thông tin User đó luôn. Kiểu như bình thường sử dụng populate thì sẽ là Comment.user_id ấy.

    ( "user_id": {
                   "_id": "5b4f090bbcb0521b24759a9c",
                   "email": "",
                   "is_admin": false,
                   "username": "hhhhh"
               }
    )
    

    Hướng dẫn lookup trong mongodb

    Thông tin các Model

    Review

    var mongoose = require('mongoose'), Schema = mongoose.Schema
    , ObjectId = Schema.ObjectId;
    var ReviewSchema = new mongoose.Schema({
      user_id: { type: ObjectId, ref: 'User' },
      book_id: { type: ObjectId },
      star: { type: Number, default: 0 },
      content: String
    },
    {
        timestamps: true   
    }
    );
    

    Comment

    var mongoose = require('mongoose'),
     Schema = mongoose.Schema,
     ObjectId = Schema.ObjectId;
    var CommentSchema = new mongoose.Schema({
      user_id: { type: ObjectId, ref: 'User' },
      review_id: { type: ObjectId, ref: 'Review' },
      content: String
    });
    

    Docs HomeMongoDB Manual

    On this page

    • Definition
    • Syntax
    • Equality Match with a Single Join Condition
    • Join Conditions and Subqueries on a Joined Collection
    • Correlated Subqueries Using Concise Syntax
    • Behavior
    • Views and Collation
    • Restrictions
    • Atlas Search Support
    • Sharded Collections
    • Slot-Based Query Execution Engine
    • Examples
    • Perform a Single Equality Join with $lookup
    • Use $lookup with an Array
    • Use $lookup with $mergeObjects
    • Perform Multiple Joins and a Correlated Subquery with $lookup
    • Perform an Uncorrelated Subquery with $lookup
    • Perform a Concise Correlated Subquery with $lookup

    $lookup

    Changed in version 5.1.

    Performs a left outer join to a collection in the same database to filter in documents from the "joined" collection for processing. The $lookup stage adds a new array field to each input document. The new array field contains the matching documents from the "joined" collection. The $lookup stage passes these reshaped documents to the next stage.

    Starting in MongoDB 5.1, $lookup works across sharded collections.

    To combine elements from two different collections, use the $unionWith pipeline stage.

    The $lookup stage has the following syntaxes:

    To perform an equality match between a field from the input documents with a field from the documents of the "joined" collection, the $lookup stage has this syntax:

    {
    $lookup:
    {
    from: ,
    localField: ,
    foreignField: ,
    as:
    }
    }

    The $lookup takes a document with these fields:

    Field

    Description

    from

    Specifies the collection in the same database to perform the join with.

    Starting in MongoDB 5.1, the collection specified in the from parameter can be sharded.

    localField

    Specifies the field from the documents input to the $lookup stage. $lookup performs an equality match on the localField to the foreignField from the documents of the from collection. If an input document does not contain the localField, the $lookup treats the field as having a value of null for matching purposes.

    foreignField

    Specifies the field from the documents in the from collection. $lookup performs an equality match on the foreignField to the localField from the input documents. If a document in the from collection does not contain the foreignField, the $lookup treats the value as null for matching purposes.

    as

    Specifies the name of the new array field to add to the input documents. The new array field contains the matching documents from the from collection. If the specified name already exists in the input document, the existing field is overwritten.

    The operation would correspond to the following pseudo-SQL statement:

    SELECT *, <output array field>
    FROM collection
    WHERE <output array field> IN (
    SELECT *
    FROM <collection to join>
    WHERE <foreignField> = <collection.localField>
    );

    See these examples:

    • Perform a Single Equality Join with $lookup

    • Use $lookup with an Array

    • Use $lookup with $mergeObjects

    MongoDB 3.6 adds support for:

    • Executing a pipeline on a joined collection.

    • Multiple join conditions.

    • Correlated and uncorrelated subqueries.

    In MongoDB, a correlated subquery is a pipeline in a $lookup stage that references document fields from a joined collection. An uncorrelated subquery does not reference joined fields.

    Note

    Starting in MongoDB 5.0, for an uncorrelated subquery in a $lookup pipeline stage containing a $sample stage, the $sampleRate operator, or the $rand operator, the subquery is always run again if repeated. Previously, depending on the subquery output size, either the subquery output was cached or the subquery was run again.

    MongoDB correlated subqueries are comparable to SQL correlated subqueries, where the inner query references outer query values. An SQL uncorrelated subquery does not reference outer query values.

    MongoDB 5.0 also supports concise correlated subqueries.

    To perform correlated and uncorrelated subqueries with two collections, and perform other join conditions besides a single equality match, use this $lookup syntax:

    {
    $lookup:
    {
    from: ,
    let: { : , …, : },
    pipeline: [ ],
    as:
    }
    }

    The $lookup stage accepts a document with these fields:

    Field

    Description

    from

    Specifies the collection in the same database to perform the join operation.

    Starting in MongoDB 5.1, the from collection can be sharded.

    let

    Optional. Specifies variables to use in the pipeline stages. Use the variable expressions to access the fields from the joined collection's documents that are input to the pipeline.

    Note

    To reference variables in pipeline stages, use the "$$" syntax.

    The let variables can be accessed by the stages in the pipeline, including additional $lookup stages nested in the pipeline.

    • A $match stage requires the use of an $expr operator to access the variables. The $expr operator allows the use of aggregation expressions inside of the $match syntax.

      Starting in MongoDB 5.0, the $eq, $lt, $lte, $gt, and $gte comparison operators placed in an $expr operator can use an index on the from collection referenced in a $lookup stage. Limitations:

      • Multikey indexes are not used.

      • Indexes are not used for comparisons where the operand is an array or the operand type is undefined.

      • Indexes are not used for comparisons with more than one field path operand.

    • Other (non-$match) stages in the pipeline do not require an $expr operator to access the variables.

    pipeline

    Specifies the pipeline to run on the joined collection. The pipeline determines the resulting documents from the joined collection. To return all documents, specify an empty pipeline [].

    The pipeline cannot include the $out stage or the $merge stage. Starting in v6.0, the pipeline can contain the Atlas Search $search stage as the first stage inside the pipeline. To learn more, see Atlas Search Support.

    The pipeline cannot directly access the joined document fields. Instead, define variables for the joined document fields using the let option and then reference the variables in the pipeline stages.

    Note

    To reference variables in pipeline stages, use the "$$" syntax.

    The let variables can be accessed by the stages in the pipeline, including additional $lookup stages nested in the pipeline.

    • A $match stage requires the use of an $expr operator to access the variables. The $expr operator allows the use of aggregation expressions inside of the $match syntax.

      Starting in MongoDB 5.0, the $eq, $lt, $lte, $gt, and $gte comparison operators placed in an $expr operator can use an index on the from collection referenced in a $lookup stage. Limitations:

      • Multikey indexes are not used.

      • Indexes are not used for comparisons where the operand is an array or the operand type is undefined.

      • Indexes are not used for comparisons with more than one field path operand.

    • Other (non-$match) stages in the pipeline do not require an $expr operator to access the variables.

    as

    Specifies the name of the new array field to add to the joined documents. The new array field contains the matching documents from the joined collection. If the specified name already exists in the joined document, the existing field is overwritten.