I am working on Neo4j database and I want to replicate the scenario mentioned below,
I have 2 nodes Product and customer. In the customer node I am storing customer id and list of products. and in the product I am storing only productid.
Customer has values {custId:1,products:[1,2,3,4]}
Product has values {productid:1},{productid:2},{productid:3},{productid:4}
Now what I want to do is,
I need to replace all these ids to an autogenerated ids after adding the nodes in the graph database. SOmething like set custId=ID(customer) and productId=ID(product) but what I am stuck at is how to iterate the list of products in customer node and change the product id to auto generated ids.
Any help is appreciated.
The idea of storing the product IDs are automatically generated by database in an array of user property - it is the wrong idea. In all senses.
The graph spirit - is to establish a relationship between the node Customer and its corresponding nodes Product, and then delete the property products from Customer and productid from Product:
MATCH (Customer:Customer)
UNWIND Customer.products as prodID
MATCH (Product:Product {productid: prodID})
MERGE (Customer)-[r:hasProduct]->(Product)
WITH Customer, count(Product) as mergedProduct
REMOVE Customer.products
WITH count(Customer) as totalMerged
MATCH (Product:Product)
REMOVE Product.productid
Related
I have the following simple graph -
I wish to build a simple recommendation system on the basis of the following example:
Consider that we have invoice 1 with an Article "Apple".
We also have invoice 2 which has "Apple" and "Oranges".
Customer of invoice 1 should be recommended "Oranges".
Basically, When a customer adds an item to an invoice, we need to recommend articles that were added to another invoice with at least one of its article in the current invoice. And the recommended article not in the current invoice.
Another way to say this -
When an article A exists in Invoice 1 AND Invoice 2 also contains article A, then list all other articles in Invoice 2 provided they do not exist in Invoice 1.
However, as a complete beginner I'm unable to figure out how to write the cypher query. Any help on how to write such a query?
Something like below should work to start with:
MATCH (i:Invoice)-[]-(a:Article)-[]-(:Invoice)-[]-(b:Article)
WHERE i.invoiceNumber = 123
RETURN b;
What is does is - start from the invoice, then navigate through the articles connected to that invoice, onto other invoices (all other invoices that share this article). From there it collects all the articles connected to those invoices.
(this assumes that you are using unique Articlenodes and connecting the invoices to them)
You can use below query for a given Customer (let say Customer1), give me other customers and recommended food based on any food that Customer1 ordered and common to other customers.
MATCH (c1:Customer {name: 'Customer1'})<-[:GENERATED_FOR]-(:Invoice)<-[:ITEMIZED_IN]-(:Article)-[:TYPE]->(f:FoodArticle)
WITH c1, collect(f) as food
MATCH (c2:Customer)<-[:GENERATED_FOR]-(:Invoice)<-[:ITEMIZED_IN]-(:Article)-[:TYPE]->(f2:FoodArticle)
WHERE c1 <> c2 AND f2 in food
WITH c2, food, collect(f2) as food2
WITH c2, [fd IN food WHERE NOT fd IN food2] as recommendations
WHERE size(recommendations) > 0
RETURN c2.name, recommendations
First, get all food that customer1 has ordered
Next, find all customers that has at least one food contained in Customer1's food
List out customer2 and collect all food for this customer2
Create a list of recommended food based on those found in customer1 food list BUT NOT found in customer2 food list
Return customer2 name and recommended food but ensure that there is at least one food in Customer1 list that is not found in customer2 list (food2)
I am trying to make database of Bookstore where customers can buy books. There is lables Book, BookCategory, Customer, Invoice. I am using relation INVOICEITEM between invoice and books. i added property netTotal in invoice to store the sum value of books related in INVOICEITEM with invoice. I tried to get total value of books which is related to invoice.
MATCH (n:Invoice {id:'inv001'})-[:INVOICEITEM]->m RETURN SUM(m.price)
and i tried to change netTotal propery of invoice by using this command.
MATCH (n:Invoice{ id: 'inv001' }) SET n.netTotal = ((n:Invoice {id:'inv001'})-[:INVOICEITEM]-> m RETURN SUM(m.price))
but it returns an error. I am new to neo4j and thank you.
The query to update netTotal on the Invoice node should be:
MATCH (n:Invoice {id: 'inv001'})-[:INVOICEITEM]->(m:Book)
WITH n, SUM(m.price) AS netTotal
SET n.netTotal = netTotal
Calculate the sum of the Book prices using a WITH statement to bring that value along to a SET statement to update the netTotal property on Invoice n. Note that you also need to specify n in the WITH statement to bring that bound variable through the query as well. More info on WITH statement here
I have a table called shoppers and another table called Users. I have a shopper_id which is the foreign key in the Shoppers table and refers to the primary key id in the Users table.
I ran a query called #shoppers = shoppers.where("some condition")
This allowed me to get a set of shoppers who satisfy the condition. Next I would like to select those Users who have the same id as the shopper_id as the individual objects in #shoppers.
I know I could do this by writing a loop, but I am wondering if ruby on rails allows me to write a Users.where condition that can help me obtain the subset of user objects with the same id as shopper_id arranged in ascending order by the name field in the Users table.
Any ideas?
Try this.
#shoppers = Shopper.where("some condition")
#users = User.where(id: #shoppers.collect(&:shopper_id)).order('name asc')
We have list of category products having duplicate names.
How to get a list of products which should not have duplicate product name in Postgres?
We are searching for min product ids with group by name.
then searching the products in ids.
category = Category.first
ids = Product.select("MIN(id) as id").where(deleted: false).group(:name).collect(&:id)
category.products.where("products.id IN (?)", ids).find_active
How can we optimize the queries?
You can do Product.all.pluck(:name).uniq to get just the product names in an array.
But I think you're solving the wrong problem, in that this problem has a bad 'smell'. If you have products that have identical names, how do you differentiate them from a UX perspective? And why only get the first created product by that name vs. the most 'popular' product? I'm trying to imagine how this solution would work for the user and I'm coming up blank, perhaps because I don't know enough about the context.
Edit: Also, could you clarify what you mean by 'should not have duplicate product name'? Is it to get a list of products, but only the first product if there's multiple products with the same name? Or are you looking for items to correct?
The simple solution in Postgres is with DISTINCT ON:
SELECT DISTINCT ON (name)
id, name -- add more columns if you need
FROM Product
WHERE deleted = FALSE
ORDER BY name, id;
Returns unique product names (sorted alphabetically). From each set of dupes the one with the smallest id. Details:
Select first row in each GROUP BY group?
Originally, I have 2 tables. I normalized it since the relationship of this tables is many to many. Now I have 3.
Jobs
jID PK
jName
jDesc
jEarnings
jTags
Course
cID PK
cName
cDesc
cSchool
cProgram
JobsCourse
ID PK
jID FK
cID FK
My app displays a tableview of the jobs
When clicked it displays the UIViewcontroller of jobs plus a tableview of the related course
How do I query the jobcourse table so that I can get all the related Courses to a certain job?
You can join the two tables, e.g.:
SELECT course.* FROM course INNER JOIN jobscourse ON jobscourse.cID = course.cID WHERE jobscourse.jID = ?
That gets all entries from course where the jID in jobscourse is equal to some value.