Talk: graph QL babysteps

Created on 22 Aug 2018  路  6Comments  路  Source: coralproject/talk

i need help on building a query to retrieve the top 10 articles/asset_urls, sort by approved comments. i am somehow to stupid to come up with a working graphQL query.

what i need to achieve is to build a box/container on our webpage, showing of the top 10 most commented articles.

any ideas?

question

Most helpful comment

yes - an internal one, i cannot share the whole one, but its basically like this:

plugins/krn/index.js

const router = require('./server/router');
module.exports = {  router};

plugins/krn/server/router.js

const Users = require("models/user");
const Comments = require("models/comment");
const Assets = require("models/asset");
const debug = require("debug")("talk:krn");
const authorization = require("../../../middleware/authorization");

const mongoose = require("../../../services/mongoose");

module.exports = async function(router) {

  router.get("/api/krn/top_commented", async function(req, res, next) {
    q = [
      {
        $match: {
          status: "ACCEPTED",
          created_at: {
            $gt: new Date(new Date().getTime() - 2 * 24 * 60 * 60 * 1000)
          }
        }
      },
      {
        $group: {
          _id: "$asset_id",
          comments: {
            $sum: 1
          }
        }
      },
      {
        $sort: {
          comments: -1
        }
      },
      {
        $limit: 10
      }
    ];
    data = await Comments.aggregate(q);
    var finala = [];
    for (record of data) {
      var asseta = await Assets.findOne({ id: record._id });
      var matches = asseta.url.match(/.*\/([0-9]+)/);
      finala.push({ count: record.comments, id: parseInt(matches[1]) });
    }
    return res.status(202).json({
      final: finala
    });
  });

  router.get("/api/krn/comment_count", async function(req, res, next) {
    var asseta = await Assets.findOne({
      url: "https://www.krone.at/" + req.query.id
    });
    if (!asseta || !asseta.id) {
      return res.status(202).json({
        count: 0
      });
    }
    q = [
      {
        $match: {
          status: "ACCEPTED",
          asset_id: asseta.id
        }
      },
      {
        $group: {
          _id: "$asset_id",
          comments: {
            $sum: 1
          }
        }
      },
      {
        $sort: {
          comments: -1
        }
      },
      {
        $limit: 10
      }
    ];
    data = await Comments.aggregate(q);
    cnt = 0;
    if (data && data.length > 0) {
      cnt = data[0].comments;
    }
    return res.status(202).json({
      count: cnt
    });
  });
};

be sure to adapt the part that matches the id's from the url

with the plugin you can call talk.domain.com/api/krn/top_commented -> you get the top 10 most commented assets in the last 48h.

with talk.domain.com/api/krn/comment_count?id=1234 - you get the amount of available comments for a given asset, based on the id (also adapt that to your needs) - this can be done via graphql already, but the solution above is a lot less ressource intense, as it is completly running on mongo.

All 6 comments

Unfortunately, our GraphQL API does not expose the edges necessary to actually perform this query. If this is something you need to get, you would have to write a plugin to support this feature.

For general information on executing GraphQL queries, see: https://docs.coralproject.net/talk/api/overview/

thx - i am going to todo it mongo side via ruby/php - to get it quickly done, and will start working on a plugin in the next weeks.

ended up doing it that way:

 router.get("/api/krn/top_commented", async function(req, res, next) {

  q = [{
    "$match": {
     "status": "ACCEPTED",
     "created_at": {
      $gt: new Date((new Date().getTime() - (2 * 24 * 60 * 60 * 1000)))
     }
    }
   },
   {

    "$group": {
     "_id": "$asset_id",
     "comments": {
      "$sum": 1
     }
    }

   },
   {
    "$sort": {
     "comments": -1
    }
   },
   {
    "$limit": 10
   }
  ]
  data = await Comments.aggregate(q)
    var finala = [];
        for(record of  data) {
                var asseta = await Assets.findOne({id: record._id });
                var matches = asseta.url.match(/.*\/([0-9]+)/);
                finala.push({count: record.comments, id: parseInt(matches[1])});
    };  
   return res.status(202).json({
    final: finala
   });

 });


once everything is setteld i ll publish a plugin in and try to find a graph-way of providing that information

@hjanuschka Did you make a plugin for it?

yes - an internal one, i cannot share the whole one, but its basically like this:

plugins/krn/index.js

const router = require('./server/router');
module.exports = {  router};

plugins/krn/server/router.js

const Users = require("models/user");
const Comments = require("models/comment");
const Assets = require("models/asset");
const debug = require("debug")("talk:krn");
const authorization = require("../../../middleware/authorization");

const mongoose = require("../../../services/mongoose");

module.exports = async function(router) {

  router.get("/api/krn/top_commented", async function(req, res, next) {
    q = [
      {
        $match: {
          status: "ACCEPTED",
          created_at: {
            $gt: new Date(new Date().getTime() - 2 * 24 * 60 * 60 * 1000)
          }
        }
      },
      {
        $group: {
          _id: "$asset_id",
          comments: {
            $sum: 1
          }
        }
      },
      {
        $sort: {
          comments: -1
        }
      },
      {
        $limit: 10
      }
    ];
    data = await Comments.aggregate(q);
    var finala = [];
    for (record of data) {
      var asseta = await Assets.findOne({ id: record._id });
      var matches = asseta.url.match(/.*\/([0-9]+)/);
      finala.push({ count: record.comments, id: parseInt(matches[1]) });
    }
    return res.status(202).json({
      final: finala
    });
  });

  router.get("/api/krn/comment_count", async function(req, res, next) {
    var asseta = await Assets.findOne({
      url: "https://www.krone.at/" + req.query.id
    });
    if (!asseta || !asseta.id) {
      return res.status(202).json({
        count: 0
      });
    }
    q = [
      {
        $match: {
          status: "ACCEPTED",
          asset_id: asseta.id
        }
      },
      {
        $group: {
          _id: "$asset_id",
          comments: {
            $sum: 1
          }
        }
      },
      {
        $sort: {
          comments: -1
        }
      },
      {
        $limit: 10
      }
    ];
    data = await Comments.aggregate(q);
    cnt = 0;
    if (data && data.length > 0) {
      cnt = data[0].comments;
    }
    return res.status(202).json({
      count: cnt
    });
  });
};

be sure to adapt the part that matches the id's from the url

with the plugin you can call talk.domain.com/api/krn/top_commented -> you get the top 10 most commented assets in the last 48h.

with talk.domain.com/api/krn/comment_count?id=1234 - you get the amount of available comments for a given asset, based on the id (also adapt that to your needs) - this can be done via graphql already, but the solution above is a lot less ressource intense, as it is completly running on mongo.

@hjanuschka Thank you for the nice explanation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aliblackwell picture aliblackwell  路  4Comments

honzie picture honzie  路  4Comments

raphaelpor picture raphaelpor  路  4Comments

tomasdev picture tomasdev  路  4Comments

schwabing picture schwabing  路  5Comments