0

I have a document collection with documents that look like the following

{
  id: "123123541234"
  items: [
    {Name = "Item 1", Amount = 12.12},
    {Name = "Item 2", Amount = 4.00},
  ]
}

I can write a sql self joined query like the following to return what I want:

select c.id, i.Name, i.Amount
from c
join i in c.items

As you can see, my doc with the id 123123541234 would be duplicated, once for each item in the nested array, so the output looks like:

[ 
  {id = "123123541234", Name = "Item 1", Amount = 12.12 }, 
  {id = "123123541234", Name = "Item 2", Amount = 4.00} 
] 

However, I'd like to use linq to write this query to keep my object references and type definition strong. I am failing to see how i can do this type of "flattening" via linq,

TL;DR: how do I do a self-join via linq to cosmosdb?

7
  • what is the ouput you need Commented Jun 29, 2018 at 17:56
  • I need [ {id = "123123541234", Name="Item 1", Amount = 12.12 }, {id="123123541234", Name="Item 2", Amount = 4.00} ] Commented Jun 29, 2018 at 19:15
  • is not it the same output you get already? Commented Jun 30, 2018 at 1:46
  • The intent is to use a linq statement, not a string query. This is because if the model changes, I will get a compilation error, not a runtime error. Commented Jun 30, 2018 at 1:47
  • what do you mean by linq query? Commented Jun 30, 2018 at 2:59

1 Answer 1

1

Assuming your types look something like this -

public class Container
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "items")]
    public Item[] Items { get; set; }
}

public class Item
{
    public string Name  { get; set; }
    public double Amount { get; set; }
}

public class FlattenedContainer
{
    public string Id { get; set; }
    public string Name { get; set; }
    public double Amount { get; set; }
}

Here is how you could do this -

var response = client.CreateDocumentQuery<Container>
            (
                UriFactory.CreateDocumentCollectionUri(...),
                new FeedOptions { ... }
            )
            .SelectMany(c => c.Items
                .Select(i => new FlattenedContainer 
                { 
                    Id = c.Id, 
                    Name = i.Name, 
                    Amount = i.Amount 
                }))
            .AsDocumentQuery();

var results = new List<FlattenedContainer>();
while (response.HasMoreResults)
{
    results.AddRange(await response.ExecuteNextAsync<FlattenedContainer>());
}
Sign up to request clarification or add additional context in comments.

2 Comments

ah, sneaky nesting! didn't think of doing it that way... does that get turned into the same query, or does it do the mapping in memory?
@NathanTregillus It ought to be the same query

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.