【问题标题】:Import CSV file to Mongo database将 CSV 文件导入 Mongo 数据库
【发布时间】:2016-07-19 12:46:49
【问题描述】:

如果我想从命令行导入 CSV 文件,我只需使用:

mongoimport -d <database> -c <collection name> --type csv --file <path to csv> --headerline

当然headerline 是可选的。就我而言,CSV 文件确实有一个标题。

我怎样才能通过 C# 做同样的事情?有没有类似的单行命令?我知道如何read a CSV file,但我很惊讶我找不到(一个?)简单的命令。

我查看了很多 online documentation,但其中大部分似乎是针对不同的 .NET 驱动程序版本;我的是 2.2.4 版。

到目前为止,这是很长的路代码(它有效,但我认为它可以更轻松地完成):

MongoClient client = new MongoClient("mongodb://127.0.0.1:27017/test"); // local database
var db = client.GetDatabase("test");

var reader = new StreamReader(File.OpenRead(@"<full path to csv")); // where <full path to csv> is the file path, of course
IMongoCollection<BsonDocument> csvFile = db.GetCollection<BsonDocument>("test");

reader.ReadLine(); // to skip header

while (!reader.EndOfStream)
{
    var line = reader.ReadLine();
    var values = line.Split(',');

        BsonDocument row = new BsonDocument
        {
            {"Column0", values[0]},
            {"Column1", values[1]},
            {"Column2", values[2]},
            {"Column3", values[3]}
        };

    csvFile.InsertOne(row);
}

这种格式的一个缺点是我必须正好有四列——我不能保证。

完美的答案将包括skip the header row

如果相关:我希望导入多个 CSV 文件,因此我会在一个目录中找到每个文件 - but I know how to do that

【问题讨论】:

  • 与其在 BsonDocument 构造函数中添加键/值对,不如创建一个包含这些对的 Dictionary,然后使用 row.AddRange(dictionary) 将其添加到 BsonDocument。

标签: c# mongodb csv import


【解决方案1】:

我使用 CSVHelper 来阅读它。 PM 控制台 -> https://www.nuget.org/packages/CsvHelper/

我已经完成了 3 个课程:

  • Program.cs(我在其中阅读了实际的 .csv 并调用了对象创建类)
  • Products.cs(集合详情和 .csv 列必须相同)
  • Mongo.cs(连接到 MongoDB 并插入或更新文档)

程序.cs:

using CsvHelper;
using System;
using System.IO;
using System.Linq;

namespace DataImport
{
    class Program
    {
        static void Main(string[] args)
        {
            // .CSV file path
            Console.WriteLine("Absolute path to .csv file: ");
            string csvFilePath = Console.ReadLine();

            // Reading .csv file line by line and calling for SendingRecord method
            using (var reader = new StreamReader(csvFilePath))
            using (var csv = new CsvReader(reader))
        {
            csv.Configuration.HasHeaderRecord = false; // My file has no header lines, if yours have this must be 'true'
            csv.Configuration.ShouldSkipRecord = record => record.All(string.IsNullOrEmpty); // Skipping empty lines in .CSV file
            var records = csv.GetRecords<Products>().ToList();
            for (int i = 0; i < records.Count; i++)
            {
                Mongo.SendingRecord(records[i]);
            }
        }
    }
}

创建的对象列表可以单独放在 mongoDB 文档中。

Products.cs:

using CsvHelper.Configuration;
using CsvHelper.Configuration.Attributes;

namespace DataImport
{
public class Products
{
    [Index(0)]
    public string prop1
    {
        get;
        set;
    }

    [Index(1)]
    public decimal prop2
    {
        get;
        set;
    }

    [Index(2)]
    public int prop3
    {
        get;
        set;
    }

public class ProductsMap : ClassMap<Products>
{
    public ProductsMap()
    {
        Map(m => m.prop1);
        Map(m => m.prop2);
        Map(m => m.prop3);
    }
}

在这里您需要指定 .csv 文件的所有行并正确映射它们。索引代表excel中的行(index0 = A,index1 = B ...)

Mongo.cs:

using MongoDB.Driver;

namespace DataImport
{
class Mongo
{
    public static void SendingRecord(Products output)
    {
        // Connecting to MongoDB
        string connectionString = "mongodb://localhost:27017";
        MongoClient mongoClient = new MongoClient(connectionString);

        // Navigating to DB and Collection
        var db = mongoClient.GetDatabase("DB-name");

        var products = db.GetCollection<Products>("Collection-Name");

        // Importing new documents or updating existing ones
        var options = new UpdateOptions();
        options.IsUpsert = true;
        products.ReplaceOne(filter: x => x.uniqueField == output.uniqueField, replacement: output, options: options);
    }
}

这是本地主机的连接字符串。为此,您需要至少一个记录的唯一值 - id、某种数字等。

如果您有任何问题,请不要犹豫。随便问问。

【讨论】:

  • 谢谢!不幸的是,我不能再验证这个解决方案(我已经转移到一个新项目)。如果其他人确认这有效,我会接受。
  • 是的。我看到它是从 3 年前开始的,但我尝试这样做了 2-3 天,并且没有真正有用的文档,所以当我设法做到这一点时,我决定分享。
  • 太好了,你有我的 +1 分享!希望对更多人有帮助。
  • 很好的解决方案,可惜这不是选择的答案
【解决方案2】:

您在 cmd 上使用该命令?我建议您使用StreamWriter 创建一个.bat 文件,然后使用Process.Start() 执行该.bat 文件,并将文件名作为参数传递给它。

更好:要在命令行上执行,请使用这个 sn-p

string command = ""; //enter any command you want
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C " + command;
process.StartInfo = startInfo;
process.Start();

【讨论】:

  • 确实,我正在考虑将其作为备用计划。但是我想肯定有办法直接在C#代码中做到这一点?
  • 谢谢,但我宁愿直接在代码中进行。我现在可以,但我认为必须有一种更有效的方法......
猜你喜欢
  • 1970-01-01
  • 2016-12-30
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-21
  • 2016-05-14
相关资源
最近更新 更多