spring mongoTemplate bulk find - spring

I've got an employee collection that looks like:
{
_id
company_id
job_type
name
age
created_at
...
}
I've for a list of company_ids and for each of them I want to get the latest 3 employees for job_type="part_time" and the latest 3 for job_type="intern" (according to the created_at field)
How can I do such a thing using one call?
An answer with mongoTemplate.bulkOps will also be valid.

To get the latest you can use the auto created _id field it has a date embedded in it. Assuming the name of your collection is employee you can use the following aggregation:
db.employee.aggregate([
{
$facet: {
"part_time": [
{
$match: {
"job_type": "part_time"
}
},
{
$match: {
"company_id": "id_from_your_list"
}
},
{ $sort: { "_id": 1 } },
{
$limit: 3
}
],
"intern": [
{
$match: {
"job_type": "intern"
}
},
{
$match: {
"company_id": "id_from_your_list"
}
},
{ $sort: { "_id": 1 } },
{
$limit: 3
}
]
}
}])
I assume that you are using spring data mongodb you can execute this aggregation operation using MongoTemplate helper.
FacetOperation facetOperation = facet().and(match(Criteria.where("job_type").is("part_time")),match(Criteria.where("company_id").is("company_id_from_your_list")),
sort(Sort.Direction.ASC, "_id"),
limit(3)).as("part_time")
.and(match(Criteria.where("job_type").is("intern")),match(Criteria.where("company_id").is("company_id_from_your_list")),
sort(Sort.Direction.ASC, "_id"),
limit(3)).as("intern");
mongoTemplate.aggregate(Aggregation.newAggregation(facetOperation), "employee", Document.class).getUniqueMappedResult();

Related

Why is my graphql query return all product?

I'm testing graphql query on Shopify GraphiQL Explorer for filtering products on Storefront API.
My query is like this:
query ProductType {
collectionByHandle(handle: "pants") {
handle
products(first: 10, filters: {
productType: "pants"
}) {
edges {
node {
handle
productType
}
}
}
}
}
And got the result like this:
{
"data": {
"collectionByHandle": {
"handle": "pants",
"products": {
"edges": [
{
"node": {
"handle": "my-test-product-pants",
"productType": "pants"
}
},
{
"node": {
"handle": "pleated-straight-pants-mens-fashion-elastic-waist-casual-pants-men-streetwear-loose-ice-silk-trousers-mens-wide-leg-pants-s-2xl",
"productType": ""
}
},
...
Basically, the result has all the products that I have for that collection. Can anybody help me with this? This is literally the code I got from shopify website
As we can see in the tutorial filters is an array
{
"product_filters": [
{
"productType": "shoes"
},
{
"productVendor": "bestshop"
},
{
"variantOption": {
"name": "color",
"value": "blue"
}
}
]
}
So, try this instead
query ProductType {
collectionByHandle(handle: "pants") {
handle
products(first:10, filters: [{ productType: "pants" ]}) {
...
}
}
}

ProjectionOperation plus and previousOperation Aggregation mongodb java

Aggregation aggregation = newAggregation(
match(Criteria.where("moment").gte(from).lte(to)),
project("pass", "carrier", "route", "iso").and("iso").as("country")
.and("$moment").plus(14400000).as("shifted"),
project("shifted").and(DateOperators.DayOfMonth.dayOfMonth("$moment")).previousOperation(),
.andExpression("$moment").dateAsFormattedString("%Y-%m-%d").as("date"),
group("pass", "carrier", "route", "country","date").count().as("total"),
sort(Sort.Direction.DESC, "pass","total")
).withOptions(newAggregationOptions().
allowDiskUse(true).build());
I am trying to do this query in java (mongodb and spring boot) that works in console (the bottom one works fine) but i failed to pass the correct date shifted already (called shifted) to the DateOperators.DayOfMonth. I get projection field must not be null so I think i am using wrong previousOperation(). How should i properly use this previousOperation? or how can i correctly shifted the date i need? thank you very much in advance.
db.billing.aggregate(
[
{
$match: { "moment": { "$gte": ISODate("2020-11-29T00:00:00Z"), "$lt": ISODate("2020-11-29T23:59:59Z")}}
},
{
$project: { "pass" :1, "carrier": 1, "moment" : { $subtract: ["$moment", 14400000 ] } }
},
{
$group: { "_id": {"pass": "$pass","carrier": "$carrier", "day": { "$dayOfMonth": "$moment"},"total": { "$sum": 1 }}}
},
{
$sort: {"_id.day":1}
}
]
)

Spring Mongo - An aggregation to order by objects in an array

I have the following data:
{
"_id": ObjectID("5e2fa881c3a1a70006c5743c"),
"name": "Some name",
"policies": [
{
"cId": "dasefa-2738-4cf0-90e0d568",
"weight": 12
},
{
"cId": "c640ad67dasd0-92f981583568",
"weight": 50
}
]
}
I'm able to query this with Spring Mongo fine, however I want to be able to order the policies by weight
At the moment I get my results fine with:
return mongoTemplate.find(query, CArea::class.java)
However say I make the following aggregations:
val unwind = Aggregation.unwind("policies")
val sort = Aggregation.sort(Sort.Direction.DESC,"policies.weight")
How can I go and actually apply those to the returned results above? I was hoping that the dot annotation would do the job in my query however didnt do anything e.g. Query().with(Sort.by(options.sortDirection, "policies.weight"))
Any help appreciated.
Thanks.
I am not familier with Spring Mongo, but I guess you can convert the following aggregation to spring code.
db.collection.aggregate([
{
$unwind: "$policies"
},
{
$sort: {
"policies.weight": -1
}
},
{
$group: {
_id: "$_id",
"policies": {
"$push": "$policies"
},
parentFields: {
$first: "$$ROOT"
}
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$parentFields",
{
policies: "$policies"
}
]
}
}
}
])
This will result:
[
{
"_id": "5e2fa881c3a1a70006c5743c",
"name": "Some name",
"policies": [
{
"cId": "c640ad67dasd0-92f981583568",
"weight": 50
},
{
"cId": "dasefa-2738-4cf0-90e0d568",
"weight": 12
}
]
}
]
Playground

AWS AppSync GraphQL - using union as mutation return causes error

I'm creating a GraphQL schema using AWS AppSync and I want to use Union as mutation return. I'd like to write mutation this way:
mutation addUpdateTariff($tariff: TariffInput!, $seasonalTimeTariff: [SeasonalTimeTariffInput!]) {
addUpdateTariff(tariff: $tariff, seasonalTimeTariff: $seasonalTimeTariff) {
id
type
values {
... on SteppedTariff {
endDate
}
... on SeasonalTimeTariff {
endDate
peakConsumption
}
}
}
}
But I'm getting this error:
Request failed with status code 400
The field values can be of the type SteppedTariff or SeasonalTimeTariff, depends the inputs of addUpdateTariff mutation. As far as I've searched, Union is only used in queries and I didn't find some documentation telling it cannot be used in a different way.
Am I missing something or I really cannot use Union this way?
Schema:
type Tariff {
id: ID!
type: TariffType!
values: [TariffValue!]
}
type SteppedTariff {
endDate: AWSDate
}
type SeasonalTimeTariff {
endDate: AWSDate
peakConsumption: Float
}
union TariffValue = SeasonalTimeTariff | SteppedTariff
Testing different schemas for Tariff values:
values: [String]
Query:
mutation addUpdateTariff($tariff: TariffInput!, $seasonalTimeTariff: [SeasonalTimeTariffInput!]) {
addUpdateTariff(tariff: $tariff, seasonalTimeTariff: $seasonalTimeTariff) {
id
type
values
}
}
Response:
{
"data": {
"addUpdateTariff": {
"id": "843eadcf-48bd-4d58-93ec-8bbe96db3635",
"type": "SeasonalTime",
"values": [
"{endDate=2019-02-02}"
]
}
}
}
values: [SeasonalTimeTariff]
Query:
mutation addUpdateTariff($tariff: TariffInput!, $seasonalTimeTariff: [SeasonalTimeTariffInput!]) {
addUpdateTariff(tariff: $tariff, seasonalTimeTariff: $seasonalTimeTariff) {
id
type
values {
endDate
}
}
}
Response:
{
"data": {
"addUpdateTariff": {
"id": "7f77c5d9-2b06-4bb8-a678-10996addc4e1",
"type": "SeasonalTime",
"values": [
{
"endDate": "2019-02-02"
}
]
}
}
}
You can definitely use Unions on the return types for mutations. Make sure you are including the field __typename on your values. Your resolver template should return something like this:
{
"id": 1,
"type": "?",
"values": [
{
"__typename": "StepTariff",
"endDate": "2019-01-01"
},
{
"__typename": "SeasonalTimeTariff",
"endDate": "2019-01-01",
"peakConsumption": 1.0
}
]
}

prismic graphql querying single user

I'm trying to figure out how to query a single user from graphql schema by id. I'm using the graphiql tool and I'm able to get all Users.
{
allPrismicUsers {
edges {
node {
id
data {
name
}
}
}
}
}
Outputs :
{
"data": {
"allPrismicUsers”: {
"edges": [
{
"node": {
"id": "Prismic__User__WzKFwywAABmiZk_4",
"data": {
"name": “John Doe”
}
}
},
{
"node": {
"id": "Prismic__User__WzKDZywAABmiZkYp",
"data": {
"name": “Jane Doe“
}
}
},
{
"node": {
"id": "Prismic__User__WzKGDiwAAJSiZlFL",
"data": {
"name": “Cat Doe”
}
}
}
]
}
}
}
I also have prismicUser() on the schema
query {
prismicUser {
id
data {
name
}
}
}
Output:
{
"data": {
"prismicUser": {
"id": "Prismic__User__WzKGDiwAAJSiZlFL",
"data": {
"name": "Cat Doe"
}
}
}
}
I'm trying to query a user based on a specific id but not sure if I'm querying the wrong way.
I tried this.
query {
prismicLocation(id: "Prismic__User__WzKDZywAABmiZkYp") {
data {
name
}
}
}
I get an error
{ "errors": [
{
"message": "Argument \"id\" has invalid value \"Prismic__User__WzKDZywAABmiZkYp\".\nExpected
\"prismicUserIdQueryString_2\", found not an object.",
"users": [
{
"line": 25,
"column": 23
}
]
} ] }
How can I call a specific user based on their id ?
According to the Gatsby GraphQL reference, Gatsby allows you to filter results by any field in GraphQL (using operators such as eq, ne, etc.)
The gatsby-source-prismic plugin provides a field called prismicId (i.e. W1syKSIAAAzdN1Jg).
Here is an example query:
{
prismicUser(prismicId:{eq:"WzKDZywAABmiZkYp"}) {
data {
name
}
}
}
But you can also query by id:
prismicUser(id:{eq:"Prismic__User__WzKDZywAABmiZkYp"})

Resources