MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Nhóm theo giá trị và điều kiện

Để thực hiện bất kỳ loại "nhóm" nào với các truy vấn MongoDB thì bạn muốn có thể sử dụng khung tổng hợp hoặc mapReduce. Khuôn khổ tổng hợp thường được ưa thích hơn vì nó sử dụng các toán tử được mã hóa gốc thay vì dịch JavaScript và do đó thường nhanh hơn.

Các câu lệnh tổng hợp chỉ có thể chạy ở phía API máy chủ, điều này có ý nghĩa vì bạn không muốn thực hiện việc này trên máy khách. Nhưng nó có thể được thực hiện ở đó và cung cấp kết quả cho khách hàng.

Với sự ghi nhận câu trả lời này để cung cấp các phương pháp xuất bản kết quả:

Meteor.publish("cardLikesDislikes", function(args) {
    var sub = this;

    var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;

    var pipeline = [
        { "$group": {
            "_id": "$card_id",
            "likes": {
                "$sum": {
                    "$cond": [
                        { "$eq": [ "$vote", 1 ] },
                        1,
                        0
                    ]
                }
            },
            "dislikes": {
                "$sum": {
                    "$cond": [
                        { "$eq": [ "$vote", 2 ] },
                        1,
                        0
                    ]
                }
            },
            "total": {
                "$sum": {
                    "$cond": [
                        { "$eq": [ "$vote", 1 ] },
                        1,
                        -1
                    ]
                }
            }
        }},
        { "$sort": { "total": -1 } }
    ];

    db.collection("server_collection_name").aggregate(        
        pipeline,
        // Need to wrap the callback so it gets called in a Fiber.
        Meteor.bindEnvironment(
            function(err, result) {
                // Add each of the results to the subscription.
                _.each(result, function(e) {
                    // Generate a random disposable id for aggregated documents
                    sub.added("client_collection_name", Random.id(), {
                        card: e._id,                        
                        likes: e.likes,
                        dislikes: e.dislikes,
                        total: e.total
                    });
                });
                sub.ready();
            },
            function(error) {
                Meteor._debug( "Error doing aggregation: " + error);
            }
        )
    );

});

Câu lệnh tổng hợp chung chỉ có một $group hoạt động trên một khóa duy nhất của "card_id". Để nhận được "lượt thích" và "lượt không thích", bạn sử dụng "biểu thức điều kiện" là $cond .

Đây là một toán tử "bậc ba" xem xét một bài kiểm tra logic trên giá trị của "phiếu bầu" và trong đó nó khớp với loại mong đợi sau đó là 1 dương được trả về, nếu không thì nó là 0 .

Sau đó, các giá trị đó được gửi đến bộ tích lũy là $sum để cộng chúng lại với nhau và tạo ra tổng số cho mỗi "card_id" bằng "thích" hoặc "không thích".

Đối với "tổng", cách hiệu quả nhất là gán giá trị "dương" cho "thích" và giá trị âm cho "không thích" cùng lúc khi thực hiện nhóm. Có một $add nhưng trong trường hợp này, việc sử dụng nó sẽ yêu cầu một giai đoạn đường ống khác. Vì vậy, chúng tôi chỉ làm điều đó trên một giai đoạn duy nhất.

Ở cuối phần này, có một $sort theo thứ tự "giảm dần" để số phiếu tích cực lớn nhất nằm trên cùng. Đây là tùy chọn và bạn có thể chỉ muốn sử dụng phía máy khách sắp xếp động. Nhưng đó là một khởi đầu tốt cho một mặc định loại bỏ chi phí phải làm điều đó.

Vì vậy, đó là thực hiện một tổng hợp có điều kiện và làm việc với các kết quả.

Danh sách thử nghiệm

Đây là những gì tôi đã thử nghiệm với một dự án sao băng mới được tạo, không có bổ trợ và chỉ một mẫu và tệp javascript

lệnh bảng điều khiển

meteor create cardtest
cd cardtest
meteor remove autopublish

Đã tạo bộ sưu tập "thẻ" trong cơ sở dữ liệu với các tài liệu được đăng trong câu hỏi. Và sau đó chỉnh sửa các tệp mặc định với nội dung bên dưới:

cardtest.js

Cards = new Meteor.Collection("cardStore");

if (Meteor.isClient) {

  Meteor.subscribe("cards");

  Template.body.helpers({
    cards: function() {
      return Cards.find({});
    }
  });

}

if (Meteor.isServer) {

  Meteor.publish("cards",function(args) {
    var sub = this;

    var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;

    var pipeline = [
      { "$group": {
        "_id": "$card_id",
        "likes": { "$sum": { "$cond": [{ "$eq": [ "$vote", 1 ] },1,0] } },
        "dislikes": { "$sum": { "$cond": [{ "$eq": [ "$vote", 2 ] },1,0] } },
        "total": { "$sum": { "$cond": [{ "$eq": [ "$vote", 1 ] },1,-1] } }
      }},
      { "$sort": { "total": -1, "_id": 1 } }

    ];

    db.collection("cards").aggregate(
      pipeline,
      Meteor.bindEnvironment(
        function(err,result) {
          _.each(result,function(e) {
            e.card_id = e._id;
            delete e._id;

            sub.added("cardStore",Random.id(), e);
          });
          sub.ready();
        },
        function(error) {
          Meteor._debug( "error running: " + error);
        }
      )
    );

  });
}

cardtest.html

<head>
  <title>cardtest</title>
</head>

<body>
  <h1>Card aggregation</h1>

  <table border="1">
    <tr>
      <th>Card_id</th>
      <th>Likes</th>
      <th>Dislikes</th>
      <th>Total</th>
    </tr>
    {{#each cards}}
      {{> card }}
    {{/each}}
  </table>

</body>

<template name="card">
  <tr>
    <td>{{card_id}}</td>
    <td>{{likes}}</td>
    <td>{{dislikes}}</td>
    <td>{{total}}</td>
  </tr>
</template>

Nội dung bộ sưu tập tổng hợp cuối cùng:

[
   {
     "_id":"Z9cg2p2vQExmCRLoM",
     "likes":3,
     "dislikes":1,
     "total":2,
     "card_id":1
   },
   {
     "_id":"KQWCS8pHHYEbiwzBA",
      "likes":2,
      "dislikes":0,
      "total":2,
      "card_id":2
   },
   {
      "_id":"KbGnfh3Lqcmjow3WN",
      "likes":1,
      "dislikes":0,
      "total":1,
      "card_id":3
   }
]


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Mongo Query với Regex trong Node JS hoạt động TRÊN MỘT BIẾN TẦN

  2. java.lang.NoClassDefFoundError khi sử dụng trình điều khiển MongoDB

  3. Cách quản lý cơ sở dữ liệu lớn một cách hiệu quả

  4. $ đầu tiên trong mongodb

  5. Draft.js - Không thể lấy dữ liệu từ cơ sở dữ liệu. Lỗi nguồn gốc chéo