Query to get top 10 users from MongoDb in Spring - spring

So basically I have a collection that looks like this(other fields omitted):
[{
user: mail1#test.com
},
{
user: mail1#test.com
},
{
user: mail1#test.com
},
{
user: mail2#test.com
},
{
user: mail2#test.com
},
{
user: mail3#test.com
}
]
I'm looking for a way to query MongoDB in order to get the top 10 active users(those with the most records in DB). Is there an easy way to get this, perhaps just using the interface?

perhaps a simple group aggregation will give you the needed result?
db.Users.aggregate(
[
{
$group: {
_id: "$user",
count: { $sum: 1 }
}
},
{
$sort: { count: -1 }
},
{
$limit: 10
},
{
$project: {
user: "$_id",
_id: 0
}
}
])

There is something called $sortByCount for aggregation.
List<UserCount> getTop10UserCount() {
return mongoTemplate.aggregate(
newAggregation(
User.class,
sortByCount("user"),
limit(10),
project("_id", "count")
),
UserCount.class
);
}
static class UserCount {
String _id;
Integer count;
// constructors, getters or setters..
}

Related

Cannot pass custom result from resolver to Graphql

I am trying to fetch data with sequelize with an attribute and pass it to graphql.
The result is fine in console but the graphql query is returning null for the attribute field.
my resolver
getUnpayedLessons: async (_, args, { models }) => {
const { Attendance, Student } = models;
return await Attendance.findAll({
include: {
model: Student,
},
where: {
fk_lessonsSerieId: { [Op.is]: null },
},
attributes: ["id", [sequelize.fn("count", sequelize.col("absenceFlag")), "unpayedLessons"]],
group: ["student.id"],
});
},
query
getUnpayedLessons {
id
unpayedLessons
student {
id
firstName
lastName
}
}
schema
type UnpayedLessons {
id: Int
unpayedLessons: Int
student: Student
}
extend type Query {
getUnpayedLessons: [UnpayedLessons]
}
and this is the console.log of the resolver when I run the query
[
attendance {
dataValues: { id: 2, unpayedLessons: 8, student: [student] },
_previousDataValues: { id: 2, unpayedLessons: 8, student: [student] },
_changed: Set {},
_options: {
isNewRecord: false,
_schema: null,
_schemaDelimiter: '',
include: [Array],
includeNames: [Array],
includeMap: [Object],
includeValidated: true,
attributes: [Array],
raw: true
},
]
and from graphql
{
"data": {
"getUnpayedLessons": [
{
"id": 2,
"unpayedLessons": null,
"student": {
"id": 2,
"__typename": "Student"
},
"__typename": "UnpayedLessons"
},
]
}
}
Any idea how I can have unpayedLessons passed to graphql?
To debug this you need to check what is returned from DB, the shape:
const values = await Attendance.findAll({...
console.log( values );
// adapt structure to match query requirements
// finally return
return values;

Using multiple mutations in one call

I have written my first script that utilises GraphQL (Still a learning curve)
Currently i am making 3 calls using GraphQL,
First is a product lookup,
Second is a Price Update,
Third is a Inventory Update.
To reduce the number of calls to the end point i wanted to merge both Price update and Inventory, But i am having 0 luck, i dont know if its bad formatting.
Here is my GraphQL Code (I am using Postman to help ensure the schema is correct before taking it to PHP)
mutation productVariantUpdate($input: ProductVariantInput!) {
productVariantUpdate(input: $input) {
product {
id
}
productVariant {
id
price
}
userErrors {
field
message
}}
second: inventoryActivate($inventoryItemId: ID!, $locationId: ID!, $available: Int) {
inventoryActivate(inventoryItemId: $inventoryItemId, locationId: $locationId, available: $available) {
inventoryLevel {
id
available
}
userErrors {
field
message
}
}
}
}
Variables:
{
"inventoryItemId": "gid://shopify/InventoryItem/XXXXXXXXXXX",
"locationId": "gid://shopify/Location/XXXXXXXXXX",
"available": 11 ,
"input": {
"id": "gid://shopify/ProductVariant/XXXXXXXXX",
"price": 55
}
}
Error i keep getting:
{
"errors": [
{
"message": "Parse error on \"$\" (VAR_SIGN) at [29, 29]",
"locations": [
{
"line": 29,
"column": 29
}
]
}
]
}
The way that you'd go about this is by specifying all your arguments at the root of your mutation, just like you did for ProductVariantInput:
mutation batchProductUpdates(
$input: ProductVariantInput!
$inventoryItemId: ID!
$locationId: ID!
$available: Int
) {
productVariantUpdate(input: $input) {
product { id }
productVariant { id price }
...
}
inventoryActivate(
inventoryItemId: $inventoryItemId
locationId: $locationId
available: $available
) {
inventoryLevel { id available }
...
}
}
Here's an example how this would work if you were to use fetch in JavaScript:
fetch("https://example.com/graphql", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
query: `
mutation MyMutation($firstId: Int, $secondId: Int) {
m1: ToggleLike(id: $firstId) {
id
}
m2: ToggleLike(id: $secondId) {
id
}
}
`,
variables: {
firstId: 1,
secondId: 2
}
})
})
Hope this helps.

Get array of repositoryOwner from GitHub GraphQL

I have this query:
query {
repositoryOwner(login: "jcubic") {
repositories(first: 20, orderBy: {field: STARGAZERS, direction: DESC}, privacy: PUBLIC) {
edges {
repository:node {
name
stargazers {
totalCount
}
}
}
}
}
}
is it possible to get multiple users intead of single one?
With help from, I was able to create query using IDs (they are from me and linus torvalds):
{
nodes(ids: ["MDQ6VXNlcjI4MDI0MQ==", "MDQ6VXNlcjEwMjQwMjU="]) {
... on User {
name
login
}
... on RepositoryOwner {
repositories(first: 20, orderBy: {field: STARGAZERS, direction: DESC}, privacy: PUBLIC) {
edges {
repository: node {
name
stargazers {
totalCount
}
}
}
}
}
}
}

Apollo Server / GraphQL - Properties of Nested Array Returning Null

Bear with me, I will explain this the best I can. Please let me know if more information is needed, I am trying to keep this as brief as possible.
I am using Apollo Server and the 'apollo-datasource-rest' plugin to access a REST API. When attempting to get the property values from a nested array of objects I get a null response for each field/property. In addition, the array being queried is only showing a single iteration when multiple are available.
The field in question is the 'cores' field within the Rocket type, i.e., launch.rocket.firstStage.cores
I have attempted various ways of mapping through 'cores' (thinking this was what it wanted) with no success.
To keep things short and simple I'm only including the code for the specific issue. All other parts of the query are operating as expected.
You can view the API response I am hitting here: https://api.spacexdata.com/v3/launches/77
schema.js
const { gql } = require('apollo-server');
const typeDefs = gql`
type Query {
singleLaunch(flightNumber: Int!): Launch
}
type Launch {
flightNumber: Int!
rocket: Rocket
}
type Rocket {
firstStage: Cores
}
type Cores {
cores: [CoreFields]
}
type CoreFields {
flight: Int
gridfins: Boolean
legs: Boolean
reused: Boolean
landingType: String
landingVehicle: String
landingSuccess: Boolean
}
`;
module.exports = typeDefs;
Data Source - launch.js
const { RESTDataSource } = require('apollo-datasource-rest');
class LaunchAPI extends RESTDataSource {
constructor() {
super();
this.baseURL = 'https://api.spacexdata.com/v3/';
}
async getLaunchById({ launchId }) {
const res = await this.get('launches', {
flight_number: launchId,
});
return this.launchReducer(res[0]);
}
launchReducer(launch) {
return {
flightNumber: launch.flight_number || 0,
rocket: {
firstStage: {
cores: [
{
flight: launch.rocket.first_stage.cores.flight,
gridfins: launch.rocket.first_stage.cores.gridfins,
legs: launch.rocket.first_stage.cores.legs,
landingType: launch.rocket.first_stage.cores.landing_type,
landingVehicle: launch.rocket.first_stage.cores.landing_vehicle,
landingSuccess: launch.rocket.first_stage.cores.landing_success,
},
],
},
};
}
}
module.exports = LaunchAPI;
resolvers.js
module.exports = {
Query: {
singleLaunch: (_, { flightNumber }, { dataSources }) =>
dataSources.launchAPI.getLaunchById({ launchId: flightNumber }),
},
};
Query
query GetLaunchById($flightNumber: Int!) {
singleLaunch(flightNumber: $flightNumber) {
flightNumber
rocket {
firstStage {
cores {
flight
gridfins
legs
reused
landingType
landingVehicle
landingSuccess
}
}
}
}
}
Expected Result
{
"data": {
"singleLaunch": {
"flightNumber": 77,
"rocket": {
"firstStage": {
"cores": [
{
"flight": 1,
"gridfins": true,
"legs": true,
"reused": true,
"landingType": "ASDS",
"landingVehicle": "OCISLY",
"landSuccess": true,
},
{
"flight": 1,
"gridfins": true,
"legs": true,
"reused": false,
"landingType": "RTLS",
"landingVehicle": "LZ-1",
"landSuccess": true
},
{
"flight": 1,
"gridfins": true,
"legs": true,
"reused": false,
"landingType": "RTLS",
"landingVehicle": "LZ-2",
"landSuccess": true
},
]
}
},
}
}
}
Actual Result (Through GraphQL Playground)
{
"data": {
"singleLaunch": {
"flightNumber": 77,
"rocket": {
"firstStage": {
"cores": [
{
"flight": null,
"gridfins": null,
"legs": null,
"reused": null,
"landingType": null,
"landingVehicle": null,
"landingSuccess": null
}
]
}
},
}
}
}
Any suggestions as to what I am doing wrong here would be greatly appreciated. Again, let me know if more information is needed.
Thank you!
Missing base url
There should be
await this.get( this.baseURL + 'launches'
IMHO there should be a map used within launchReducer to return an array, sth like:
launchReducer(launch) {
return {
flightNumber: launch.flight_number || 0,
rocket: {
firstStage: {
cores: launch.rocket.first_stage.cores.map(core => ({
flight: core.flight,
gridfins: core.gridfins,
legs: core.legs,
landingType: core.landing_type,
landingVehicle: core.landing_vehicle,
landSuccess: core.land_success,
})),
},
},
};
}
.map(core => ({ is for returning object [literal], the same as/shorter version of .map(core => { return {

Issues with GraphQL Nested Mutation

I am trying to achieve nesting mutation by adding player name in Team (Parent) and struggling trying to fetch list of player name...
Inside GraphiQL tool (localhost:4000/graphiql), this is the Add Mutation variable that I have included...
mutation AddPlayerToTeam($name: String!, $teamId: ID!){
addPlayerToTeam(player: $name, teamId: $teamId){
id
players{
name
}
}
}
The query variables, adding teamID and name...
{
"teamId": "5aff545371fc930a4c43b2b9",
"name": "John Doe"
}
The result shown...
{
"data": {
"addPlayerToTeam": {
"id": "5b072774e385740c38483111",
"players": []
}
}
}
But I was expecting for player name to show up like this....
{
"data": {
"addPlayerToTeam": {
"id": "5b072774e385740c38483111",
"players": [
{
"name": "John Doe"
}
]
}
}
}
The mutation code...
AddPlayerToTeam: {
type: TeamType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
teamId: { type: new GraphQLNonNull(GraphQLID) }
},
resolve(parent, { name, teamId }) {
let addPlayer = new Player({ name, teamId });
return addPlayer.save();
}
},
I've struggled to find reason why I am getting "players": [] instead of "players": [ {"name": "John Doe" } ].
Need I include .then(...) after .save() to get result? Any examples? Your help is appreciated.
BTW, I using mongoDB/mongoose method. Saving them in local mongoDB.
Found solution for this... Thank #andrewingram from graphql.slack for helping. Just include .then(...) to return result.
AddPlayerToTeam: {
type: TeamType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
teamId: { type: new GraphQLNonNull(GraphQLID) }
},
async resolve(parent, { name, teamId }) {
let addPlayer = new Player({ name, teamId });
await addPlayer.save();
return Team.findById(teamId);
}
},
or in promise version
resolve(parent, { name, teamId }) {
let addPlayer = new Player({ name, teamId });
return addPlayer.save().then(() => Team.findById(teamId));
}
Hope that help.

Resources