1

I am stuck in a problem where I need to convert a list into Dictionary > BsonDocument to import in MongoDB.

The list has the name of column and the values to insert in that column. But I am getting key already exits exception as soon the compiler enter in loop. Any suggestion?

void Main()
{
    List<ListRow> myList = new List<ListRow>();
    myList.Add(new ListRow { columnName = "column1", results = new List<string> { "a1", "b1", "c1" } });
    myList.Add(new ListRow { columnName = "column2", results = new List<string> { "a2", "b2", "c2" } });
    myList.Add(new ListRow { columnName = "column3", results = new List<string> { "a3", "b3", "c3" } });

    List<BsonDocument> batch = new List<BsonDocument>();
    foreach (var row in myList)
    {
        var dictionary = row.results.ToDictionary(x => row.columnName, x => x);
        batch.Add(dictionary);
    }
    // Print batch
    // Add to MongoDB
}

public class ListRow
{
    public string columnName { get; set; }
    public List<string> results { get; set; }
}

Expected result to pull

enter image description here

Vikash Rathee
  • 1,776
  • 2
  • 25
  • 43

3 Answers3

1

You are trying to make an entry in the iteration. ToDictionary aims for create the whole dictionary.

class Program
{
    static void Main(string[] args)
    {
        List<ListRow> myList = new List<ListRow>
        {
            new ListRow {columnName = "column1", results = new List<string> {"a1", "b1", "c1"}},
            new ListRow {columnName = "column2", results = new List<string> {"a2", "b2", "c2"}},
            new ListRow {columnName = "column3", results = new List<string> {"a3", "b3", "c3"}}
        };

        BsonDocument batch = myList.ToDictionary(x => x.columnName, x => x.results).ToBsonDocument();
        // Print batch
        // Add to MongoDB
    }
}

public class ListRow
{
    public string columnName { get; set; }
    public List<string> results { get; set; }
}
ntohl
  • 2,067
  • 1
  • 28
  • 32
  • It convert complete list into single document. While I need to store each list result as separate document to pull via api. For example a1-a3 as document1, b1-b3 as document 2 etc. See expected result in my update. – Vikash Rathee Jan 29 '19 at 10:07
  • Can you show us an example in JSON format. What you have written "separate document" for me, means `db.document1.find()` results in `[ "a1", "a2", "a3" ]`? – ntohl Jan 29 '19 at 20:57
0

Your key : row.columName is repeated when the list is flatten to a dictionary. You can try to generate an unique key for each list item.

    List<BsonDocument> batch = new List<BsonDocument>();
    foreach (var row in myList)
    {
        var i = 0;
        var dictionary = row.results.ToDictionary(x => $"{row.columnName}_{++i}", x => x);
        batch.Add(dictionary);
    }
Yves Israel
  • 408
  • 3
  • 5
  • 1
    columnName are already unique. I think the main problem was the misunderstanding how `ToDictionary` work. But yes. That is a viable solution too, if the `x => x` is really intended. – ntohl Jan 27 '19 at 11:36
0

Ok. If I understand the problem correctly, you want to first transpose the matrix of

"a1", "b1", "c1"
"a2", "b2", "c2"
"a3", "b3", "c3"

than name the columns with column1, column2, column3, etc.. For the transpose problem I got this solution.

From there I worked out this solution, where I needed a root node, which is not clear how should look like from the question>

class Program
{
    static void Main(string[] args)
    {
        List<ListRow> myList = new List<ListRow>
        {
            new ListRow {columnName = "column1", results = new List<string> {"a1", "b1", "c1"}},
            new ListRow {columnName = "column2", results = new List<string> {"a2", "b2", "c2"}},
            new ListRow {columnName = "column3", results = new List<string> {"a3", "b3", "c3"}}
        };

        var result = myList
            .SelectMany(listRow => listRow.results.Select((item, index) => new {item, index}))
            .GroupBy(i => i.index, i => i.item)
            .Select(g => g.Select((x, index) => new {Col = myList[index].columnName, Value = x})
                .ToDictionary(x => x.Col, x => x.Value))
            .ToList();

        BsonDocument batch = new Dictionary<string, List<Dictionary<string, string>>> {{"root", result}}
            .ToBsonDocument();
        // {{ "root" : [{ "column1" : "a1", "column2" : "a2", "column3" : "a3" }, { "column1" : "b1", "column2" : "b2", "column3" : "b3" }, { "column1" : "c1", "column2" : "c2", "column3" : "c3" }] }}
        // or just
        BsonArray batchPart = BsonArray.Create(result);
        // {[{ "column1" : "a1", "column2" : "a2", "column3" : "a3" }, { "column1" : "b1", "column2" : "b2", "column3" : "b3" }, { "column1" : "c1", "column2" : "c2", "column3" : "c3" }]}
        // Print batch
        // Add to MongoDB
    }
}

public class ListRow
{
    public string columnName { get; set; }
    public List<string> results { get; set; }
}
ntohl
  • 2,067
  • 1
  • 28
  • 32