Update Array inside Node

I have an Item that has a market history.

type Item {
  name: String! @id
  marketHistory: [MarketDataPoint] @hasInverse(field: item)
}

type MarketDataPoint {
  item: Item!
  timestamp: Int64!
  price: Float!
}

Every day I get an updated full marketHistory that contains all previous datapoints as well, so I would update the Item with upsert = true. The problem is that the upsert option appends to the marketHistory array, therefore creating duplicates. The timestamps can’t be unique with @id because I have multiple Items with the same timestamp.

I have tried to delete the marketHistory before every upsert, but I can’t get it to work. It says

Field "item" is not defined by type MarketDataPointFilter.

mutation DeleteMarketData {
  deleteMarketDataPoint(
    filter: {
        item: {
          name: {eq: "test"}
        }
    },
  ) {
    msg
  }
}

I have tried it with updateItem and then calling remove: {marketData: } but it doesn’t work either.

Is there a solution to this or is my procedure of updating the marketData a bad idea? Should I instead only push the new data, in which case I would have to query the marketData first and find out about the last timestamp?

Have you tried replacing the entire array when you upsert?

How do I do that? If I upsert and put one single element inside of market Data, it will append it do the old array and create duplicates

As of now we can’t have nested fields in the filter. So, having a filter on item name from deleteMarketDataPoint mutations is not allowed. We are currently working on nested filters here:

Upsert also doesn’t update the nested fields, it just searches nested fields based on @id values and either links to an existing node or creates a node and then links it. But in your case there is no @id field inside MarketDataPoint, so every time you do upsert it adds a new MarketDataPoint and link to the Item.

you can delete MarketDataPoint objects using timestamp or price as follows. Make sure to add the @search directive on fields which you want to use in the filter.

mutation DeleteMarketData {
  deleteMarketDataPoint(
    filter: { timestamp:{eq:"100"}
        
      },
  ) {
    msg
  }
}

you can also delete the complete Item object and then insert that with new market data points.

mutation DeleteItem {
  deleteItem(
    filter: { name:{eq:"Alice"}
        
      },
  ) {
    msg
  }
}

If you want to remove using updateMutation then you need to add the @id field inside MarketDataPoint type. Because remove needs @id or ID field for the nested object. For example, if you have dataPointID as @id field inside market history then you can use below to individually delete market data points.
But yeah, you can’t delete all of them in one go.

mutation{
  updateItem(input:{ 
		filter: {
			name: { eq: "Alice" } 
  },
  remove:{
     marketHistory:[{dataPointID:"D01"},{dataPointID:"D02"}]
  }  
	}
  ){
    item{
    name
   
    }
  }
}

It’s a nice use case and i do feel need to have filter object in remove or some other method to remove all the nodes in nested object. We will discuss it and try to add something around it.
Thanks.

2 Likes

i am accepting it as a bug and will add way to delete all nested objects.

2 Likes