Looking for a LINQ implementation to handle following use case.
Pesudo definitions of object:
class Product{
int Id;
string Name;
IList<ProductAttribute> ProductAttributes;
}
class ProductAttribute{
int Id;
string Name;
string Value;
}
I have collection of products that look something like:
[
{"Name":"Red Large Shirt", "ProductAttributes": [{"Name": "Color", Value:"Red"},{"Name":"Size", "Value":"Large"}, {"Name":"Type", "Value":"Shirt"}]},
{"Name":"Red Small Shirt", "ProductAttributes": [{"Name": "Color", Value:"Red"},{"Name":"Size", "Value":"Small"}, {"Name":"Type", "Value":"Shirt"}]},
{"Name":"Red Large Pant", "ProductAttributes": [{"Name": "Color", Value:"Red"},{"Name":"Size", "Value":"Large"}, {"Name":"Type", "Value":"Pant"}]},
{"Name":"Blue Large Shirt", "ProductAttributes": [{"Name": "Color", Value:"Blue"},{"Name":"Size", "Value":"Large"}, {"Name:"Type", "Value":"Shirt"}]},
]
I need a LINQ statement that returns list of products that match certain attributes.
E.g. Return list of product where ProductAttribute ("Name"="Size" && "Value"="Large") && ("Name"="Color" && "Value" = "Red")
Thanks
You need to use .Any() or .Contains() extension. For example,
products.Where(p=>p.ProductAttributes.Any(a=>a...condition here for attributes))
Related
I am showing some data to the user:
{
"id": 3,
"name": "AB:11",
"description": "AB:11 is an Imperial Black Barley Wine brewed with ginger, black raspberries and chipotle peppers. A 12.8% rollercoaster of ginger zestiness and chipotle smokiness, all bound together with dark berry tartness and the decadent residual body of a Black Barley Wine.",
"method": {
"id": 3,
"mash_temp": [
{
"id": 6,
"temp": {
"value": 68,
"unit": "celsius"
}
}
]
}
}
But, I want to show it without "method" I only need to show what is inside "mesh_temp" field,so it would be something like this:
"id": 3,
"name": "AB:11",
"description": "AB:11 is an Imperial Black Barley Wine brewed with ginger, black raspberries and chipotle peppers. A 12.8% rollercoaster of ginger zestiness and chipotle smokiness, all bound together with dark berry tartness and the decadent residual body of a Black Barley Wine.",
"mash_temp": [
{
"temp": {
"value": 68,
"unit": "celsius"
}
}
]
}
Also, like you can see in first example I don't want to show id of the mesh_temp
Those are my Entities:
Beer: Beer class
Method: Method class
Mash Temp: MashTemp class
Temp: Temp class
So just to summarize: I want to show only: id, name, description and mash_temp field (without id). Any advices how to do this?
The simplest way is to create a DTO that is used in the response on your API with exactly the attributes you want. This is in fact a suggested pattern exactly because of use cases similar to this one: when your internal model is different from the model you want to make available via your API.
Just like I answered your other question, I would suggest a DTO approach with Blaze-Persistence Entity-Views: How to show data to user with DTO
Create a Model class as shown below and set the required fields
public class MyData {
private Long id;
private String name;
private String description;
private List<MashTemp> mash_temp;
}
class MashTemp {
private String temp;
private Integer value;
private String unit;
}
Let's imagine we have GraphQL API that can return an object Entity with Id and Name properties and I requested Name only:
query {
entities {
name
}
}
And it returns
{
"data": {
"entities": [
{
"name": "Name1"
},
{
"name": "Name2"
}
]
}
}
But what if I want to have only the name of entities as a scalar type? In other words, I want to have something like:
{
"data": {
"entities": [
"Name1",
"Name2"
]
}
}
Is it possible to have such result without changes on the GraphQL API side? Aliases, Fragments, etc. GraphQL has a lot of built-in query capabilities, but none of the known me can return complex objects as scalar type.
what you're asking for is almost impossible if you don't want to change the type definition for Entities.
This: 👇🏽
Entity: id: int! name: String
entities(): [Entity]
returns an array of objects with keys name and id.
To achieve what you're asking you either change Entity to be just a string or have your client reduce that object to an array of just Entity names when they receive it.
They could do something like this:
const data = {
entities: [
{
name: 'Name1',
},
{
name: 'Name2',
},
],
};
const entityNames = data.entities.reduce(
(acc, curr) => [...acc, curr.name],
[]
);
console.log(entityNames);
I'm new at Laravel and Programming at that. I have a problem joining model with its relationship, here is what my model:
class MainClass extends Model
{
public function first()
{
return $this->hasMany(First::class);
}
public function second()
{
return $this->hasMany(Second::class);
}
public function third()
{
return $this->hasMany(Third::class);
}
}
When i try to get MainClass records then load it's relationship like:
$main = Main::where('status', 'ready')->get()
$main->load(['first','second'])
Here's what i got:
[{
"id":"1",
"name":"First Person",
"status": "ready",
"first":[
{"main_id": "1", "prop":"One"},
{"main_id":"1", "prop":"Two"}],
"second":[
{"main_id": "1", "other":"Yes"},
{"main_id":"1", "other":"Two"},
{"main_id":"1", "other":"Three"}]
},{
"id":"5",
"name":"Fifth Person",
"status": "ready",
"first":[
{"main_id": "5", "prop":"Five"},
{"main_id":"5", "prop":"Six"}],
"second":[
{"main_id": "5", "other":"Laptop"},
{"main_id":"5", "other":"Pc"}]
}]
How can i merge that relationship so the result will be like join query,
this is what i want:
[{
"id":"1",
"name":"First Person",
"status": "ready",
"prop":"One",
"other:"Yes"
},{
"id":"1",
"name":"First Person",
"status": "ready",
"prop":"Two",
"other":"Two"
}]
I know there is a way to combine collection with merge or push in laravel, but i can't seem to get it right.
As of why not using join query, because i want to load relationship dynamically, so relation is not always loaded, but sometime they do. While join query, i have to write it manually (as far as i know) :-)
Maybe someone can point me somewhere, or maybe there is a package for something like this?
Thanks in advance
Use eager loading, fetching the collection, then run groupBy, then the each, then the map function to return the results formatted as your wish.
Why not just simply run the joins
You can do it with join;
$main = Main::query()->select(['main.id', 'main.name', 'main.status', 'f.prop', 's.other', 't.blabla'])
->leftJoin('first as f', 'f.main_id', 'main.id')
->leftJoin('second as s', 's.main_id', 'main.id')
->leftJoin('third as t', 't.main_id', 'main.id')
->where('main.status', 'ready')
->get();
A few Documents that already stored in Mongo db:
{
"companyName": "Google",
"departmentName": "Sales"
},
{
"companyName": "Google",
"departmentName": "HR"
},
{
"companyName": "Amazon",
"departmentName": "Marketing"
}
I need to implement a method that will receive 2 attributes: companyName, departmentName (one of them can be optional) and will return a list of found documents, for example:
when departmentName is null and companyName is Google method returns 2 documents:
{
"companyName": "Google",
"departmentName": "Sales"
},
{
"companyName": "Google",
"departmentName": "HR"
}
when companyName is null and departmentName is Marketing only one Document returned:
{
"companyName": "Amazon",
"departmentName": "Marketing"
}
I tried to implement it in various ways, but no one fits my needs:
public interface CompanyRepository extends ReactiveMongoRepository<Company, String> {
Flux<Company> findByCompanyNameAndDepartmentName(String companyName, String departmentName);
}
returns 0 results, when companyName or departmentName is null.
Option 2:
Company company = Company.builder()
.companyName(null)
.departmentName("Marketing")
.build();
repository.findAll(Example.of(company))
.subscribe(System.out::println);
is also prints 0 results, but I expect to see one document.
so, please advice for to implement proper search?
Could you try with the below repository interface:
public interface CompanyRepository extends ReactiveMongoRepository<Company, String> {
Flux<Company> findByCompanyNameOrDepartmentName(String companyName, String departmentName);
}
Change is JPA method name change from findByCompanyNameAndDepartmentName to findByCompanyNameOrDepartmentName. Since you need the result if any one of the field matches your input.
Reference: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation
if I have a collection of books :-
{author: "tolstoy", title:"war & peace", price:100, pages:800}
{author: "tolstoy", title:"Ivan Ilyich", price:50, pages:100}
and if i want a result like this after grouping them by author :-
{ author: "tolstoy",
books: [
{author: "tolstoy", title:"war & peace", price:100, pages:800}
{author: "tolstoy", title:"Ivan Ilyich", price:50, pages:100}
]
}
using raw mongo queries I can do something like this:-
{$group: {
_id: "$author",
books:{$push: {author:"$author", title:"$title", price:"$price", pages:"$pages"}},
}}
But how do I do this using spring , I tried something like this:-
private GroupOperation getGroupOperation() {
return group("author").push("title").as("title").push("price").as("price").push("pages").as("pages");
}
but this does not seem to work. Any help would be appreciated.
UPDATE:-
I used the solution as in the link suggested by #Veeram and it works great but I ran into another issue when I project it. I have my projection class which looks like:-
public class BookSummary{
private String author;
private List<Book> bookList;
//all getters and setters below
}
The group method looks like this:-
private GroupOperation getGroupOperation() {
return group("author").push(new BasicDBObject("id","$_id").append("title","$title").append("pages","$pages").append("price","$price")).as("bookList");
}
the projection method looks like this:-
private ProjectionOperation getProjectOperation() {
return project("author").and("bookList").as("bookList");
}
and the final aggregation operation:-
mongoTemplate.aggregate(Aggregation.newAggregation(groupOperation,projectionOperation), Book.class, BookSummary.class).getMappedResults();
However this gives the result:-
[
{
"author": null,
"bookList": [
{
"id": null,
"title": "title1",
"pages": "100",
"price":"some price"
},
{
"id": null,
"title": "title2",
"pages": "200",
"price":"some price"
}
]
}
]
Why is the author and id null here? Any help would be appreciated
You should be projecting using _id instead in the project phase.
private ProjectionOperation getProjectOperation() {
return project("_id").and("bookList").as("bookList");
}