这里采用的是mongoDB官网推荐使用.net驱动:

DOC

 

有关于MongoDB的安装读者可以参考其他的博客,对于基本的学习来说并不需要进行过多的配置。

参考链接

 

 

创建连接

BSON类库

BSON是类似JSON的一种二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。它也是MongoDB文档数据库内部的数据存储方式。

public enum BsonType {
    Double = 0x01,
    String = 0x02,
    Document = 0x03,
    Array = 0x04,
    Binary = 0x05,
    Undefined = 0x06,
    ObjectId = 0x07,
    Boolean = 0x08,
    DateTime = 0x09,
    Null = 0x0a,
    RegularExpression = 0x0b,
    JavaScript = 0x0d,
    Symbol = 0x0e,
    JavaScriptWithScope = 0x0f,
    Int32 = 0x10,
    Timestamp = 0x11,
    Int64 = 0x12,
    MinKey = 0xff,
    MaxKey = 0x7f
}

这一步骤跟ADO.NET连接到数据库的步骤是一样的,ADO.NET是利用SqlConnection连接数据库,而MongoDB则使用MongoClient连接,并在构造函数中将连接字符传递进去,当然可以不传递,那么默认就是连接本地的计算机的默认端口(27017),比如下面的三种连接方式:

 

1 var client = new MongoClient();
2
3 var client1 = new MongoClient(“mongodb://localhost:27017”);
4
5 var client2 = new
MongoClient(“mongodb://localhost:27017,localhost:27018,localhost:27019”);

 

 

 

 

BsonValue和子类

获取数据库

BsonValue是一种代表BsonType的虚拟类。它是BsonType枚举类的凝聚子类。

为了获取数据库,只需要调用MongoClient对象的GetDatabase方法,并传入数据库名称即可,如果数据库存在则直接返回,否则就创建该数据库并返回,比如下面的这段代码将创建名为“foo”的数据库:

·可以使用public构造函数生成BsonValue子类

var database = client.GetDatabase(“foo”);
现在database变量就指向了foo数据库了。

·使用静态create函数生成

 

·Use a static property of a subclass of BsonValue(静态的子类属性?)

获取链表

·隐式转换成BsonValue

虽然叫获取链表,但是实际上就是获取数据库中的表,我们可以通过上面database的GetCollection<TDocument>方法获取,比如下面的代码我们将获取一个名为“bar”的表:

BsonType的类型

var collection = database.GetCollection<BsonDocument>(“bar”);
我们传入的泛型参数为BsonDocument,这个是自带的,可以动态的容纳各种格式的数据,当然这里还是建议读者使用POCO。

可以用下面的例子代码确认BsonValue的属性

 

BsonValue value;
if (value.BsonType == BsonType.Int32) {
    // we know value is an instance of BsonInt32
}
if (value is BsonInt32) {
    // another way to tell that value is a BsonInt32
}
if (value.IsInt32) {
    // the easiest way to tell that value is a BsonInt32
}

插入一个文档

  

利用collection对象,我们可以将文档插入其中,比如下面的json格式数据:

 

{
     “name”: “MongoDB”,
     “type”: “database”,
     “count”: 1,
     “info”: {
         x: 203,
         y: 102
     }
}

BsonElement

下面我们利用BsonDocument对象组织上面的JSON格式的数据:

(Bson元素)

Bson元素是一个name/value的键值对。

document.Add(new BsonElement("age", 21)); // OK, but next line is shorter
document.Add("age", 21); // creates BsonElement automatically

var document = new BsonDocument
{
    {“name”,”MongoDB”},
    {“type”,”Database”},
   {“count”,1},
   {“info”,new BsonDocument{
         {“x”,203},
         {“y”,102}
       }
   }
};

BsonDocument

然后我们利用collection对象的InsertOneAsync将上面的数据插入其中:

 

BsonDocument是name/value键值对的集合。

BsonDocument构造函数

collection.InsertOneAsync(doc);
我们都知道Async为后缀的方法都是支持异步的,但是笔者是在控制台项目中演示的所以没有加上这个await,如果读者实在其他的环境中测试的可以根据情况加上。

  • BsonDocument()
  • BsonDocument(string name, BsonValue value)

 

插入多个文档

参考

如果需要一次性插入多个文档,我们可以通过InsertManyAsync方法,比如下面的示例我们将插入100条数据:

Thread safety(多线程问题)

var documents = Enumerable.Range(0, 100).Select(x => new
BsonDocument(“counter”, x));
collection.InsertManyAsync(documents);
 

只有少部分的C#
Driver类是多线程安全的。比如MongoClient,MongoServer,MongoDatabase,
MongoCollection
以及MongoGridFS。一般常用的类存在多线程问题,包括MongoCursor以及Bson类库中的所有类(除了其中的BsonSymbolTable是线程安全的)。

 

所有的类的静态属性值和函数方法都不会引起多线程问题。

统计文档数量

 

通过上面的步骤我们已经插入了101条数据,如果在实际开发中我们需要统计数据的数量就可以通过调用CountAsync方法,比如下面的代码:

 

var count = collection.CountAsync(new BsonDocument());
Console.WriteLine(count.Result);
 

 

 

MongoClient类

查询链表

 

利用Find方法我们可以对链表进行查询,Find方法将返回给我们IFindFluent<TDocument,TProjection>对象,该接口属于链式接口,所以能够提供给我们类似jquery那样的链式变成方式去控制查询操作。

这个类提供使用MongoDB
server的基本对象。与MongoDB
server服务进行链接的时候,client自动进行连接。(使用了连接池来进行更有效的连接)

 

 

查询链表首条数据

在连接一个副本集的时候,有且只用一个MongoClient实例。

为了获取第一条数据我们可以通过调用FirstOrDefaultAsync方法,该方法会返回第一条数据,如果不存在数据则会返回null,比如下面的代码将会显示链表中的第一条数据:

 

var firstDoc = collection.Find(new
BsonDocument()).FirstOrDefaultAsync();
Console.WriteLine(firstDoc.Result.ToString());
如果读者注意最后的输出,会发现一个_id字段,但是我们并没有插入这个字段,这个字段是mongoDB自动加入的,相信很多人都知道它的作用,这里就不详细解释额。

When you are connecting to a replica set you will still use only one
instance of MongoClient, which represents the replica set as a whole.
The driver automatically finds all the members of the replica set and
identifies the current primary.

 

 

查询链表中所有数据

这个类的实例不会引起多线程问题。

如果想将链表中所有的数据都返回可以在Find操作之后调用ToListAsync方法就可以,将会直接返回List<T>类型的结果,比如下面的这段代码:

 

var documents = collection.Find(new
BsonDocument()).ToListAsync().Result;
针对数量较少的数据情况下,上面这种方式是没有问题,但如果我们需要处理大量的数据,那么我们就不能使用上面的这种方式,就需要利用下面的方式,通过ForEachAsync来完成,因为这个方法会在每条数据返回的时候执行一个回调,从而达到并发处理的目的,比如下面这段代码就演示了如何使用:

除非其他设置,在默认设置情况下,所有操作需要一个WriteConcern,一个写入确定语句。另外,默认情况下,所有的写操作会锁定,直到server知道要进行写操作。

collection.Find(new BsonDocument()).ForEachAsync(x =>
Console.WriteLine(x));
 

 

 

 

通过条件查询单条数据

 

我们可以在调用Find方法的时候传入一个过滤条件,从而在链表中查询我们希望的数据,比如下面这个例子我们将查询字段“counter”的值为71的数据:

MongoServer class

var filter = Builders<BsonDocument>.Filter.Eq(“counter”, 71);
var document = collection.Find(filter).FirstAsync().Result;
Console.WriteLine(document);
这里我们需要通过Builders的静态对象Filter中的各种条件方法来构造条件,然后在调用Find方法的将其传入即可。

 

 

 

通过条件查询多条数据

 

我们也可以获取多条数据,比如下面这个例子,我们将搜索出所有“counter”的值大于50的数据:

使用MongoServer类可以进行更多的控制操作。它使用了先进的技术通过一个单个的socket获取数据库以及进行一系列的数据库操作,并且保持数据库的一致性。

var filter = Builders<BsonDocument>.Filter.Gt(“counter”, 50);
var document = collection.Find(filter).ForEachAsync(x =>
Console.WriteLine(x));
 

 

当然我们也可以给定一个范围,比如50到70之间:

 

var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Gt(“counter”, 50) &
filterBuilder.Lt(“counter”, 70);
collection.Find(filter).ForEachAsync(x => Console.WriteLine(x));
 

MongoDatabase class

这是一个描述MongoDB Server的类。通常情况下,一个database只有一个这个类的实例,除非你使用了不同的设置连接了相同的database。因为在这个情况下面,针对每个设置,都有一个实例。

 

 

对数据排序

 

下面我们将在查询的基础之上加上排序,排序只需要在在调用Sort方法时传入对应的参数即可,比如下面的例子,我们将对链表先进行查询,然后排序:

MongoCursor<TDocument>类

var filter = Builders<BsonDocument>.Filter.Exists(“counter”);
var sort = Builders<BsonDocument>.Sort.Descending(“counter”);
var documnt = collection.Find(filter).Sort(sort).FirstAsync().Result;
 

Find函数不会直接返回确切的查询结果。而是它返回一个游标来枚举检索查询结果。这个query查询语句实际上在你尝试检索第一个结果的时候才会送至服务器。这意味着,你可以通过控制游标检索结果来得到你感兴趣的内容。

 

MongoCursor类的实例会造成多线程问题。至少在它被冻结之前不要使用。一旦它是冻结状态下,它就不会造成多线程安全问题。因为它是只读状态。

对字段投射

 

许多时候我们并不需要文档中的所有数据,这就好比在SQL中我们都会只把我们需要的数据select出来,而不会把表中的所有字段的数据都拿出来,自然MongoDB也可以让我这样做,我们只需要跟过滤和排序一样利用Projection构造器来构造然后传递给Project方法中就可以了,下面这个例子中我们将排除“_id”字段:

 

var projection =
Builders<BsonDocument>.Projection.Exclude(“_id”);
var document = collection.Find(new
BsonDocument()).Project(projection).FirstAsync().Result;
Console.WriteLine(document);
 

WriteConcern class

 

WriteConcern 有很多等级,这个类就是用来描述这个等级的。WriteConcern
应用只用来操作那些没有返回的操作。比如Insert 、Save、Update和Remove。

更新文档

这个主要就是当Insert、Save、Update和Remove指令发送给服务器之后,会有一个GetLassError命令来确认这些操作是否成功执行了。

MongoDB拥有很多更新操作,下面我们将会介绍几个简单的并且常用的更新操作。

 

 

 

如果我们需要更新一个对象(如果条件不匹配那么可能是0条),可以使用UpdateOneAsync方法,并执行过滤条件和需要更新到的文档,比如下面我们将“counter”为1的数据中的“counter”更新为110:

 

var filter = Builders<BsonDocument>.Filter.Eq(“counter”, 1);
var updated = Builders<BsonDocument>.Update.Set(“counter”, 110);
var result = collection.UpdateOneAsync(filter, updated).Result;
 

 

如果我们需要批量的更新,我们可以调用UpdateManyAsync即可。比如我们需要将“counter”小于10的数据中的“counter”累加100,那么我们就可以像下面这样来写:

 

var filter = Builders<BsonDocument>.Filter.Lt(“counter”, 10);
var updated = Builders<BsonDocument>.Update.Inc(“counter”, 100);
var result = collection.UpdateManyAsync(filter, updated).Result;
 

 

 

client:The
MongoClient
instance actually represents a pool of connections to the database; you
will only need one instance of class MongoClient even with multiple
threads

删除文档

  var client = new MongoClient(“mongodb://localhost:27017,localhost:27018,localhost:27019”);

作为基础部分这也是最后一个部分了,利用上面的过滤,然后调用DeleteOneAsync或DeleteManyAsync方法就可以了,比如下面的列子就是删除“counter”大于100的所有数据:

 

var filter = Builders<BsonDocument>.Filter.Gt(“counter”, 100);
var resut = collection.DeleteManyAsync(filter).Result;

database:To get a database, specify the name of the database to the
GetDatabase
method on client. It’s ok if the database doesn’t yet exist. It will
be created upon first use.

   var database = client.GetDatabase(“foo”);

  var collection =
database.GetCollection<BsonDocument>(“bar”);//The collection variable now holds a
reference to the “bar” collection in the “foo”
database.

  

document:Once you have the collection instance, you can insert
documents into the collection

var document = new BsonDocument
{
    { "name", "MongoDB" },
    { "type", "Database" },
    { "count", 1 },
    { "info", new BsonDocument
        {
            { "x", 203 },
            { "y", 102 }
        }}
};

  collection.InsertOne(document);

  await
collection.InsertOneAsync(document);

  var documents
= Enumerable.Range(0, 100).Select(i => new
BsonDocument(“counter”,
i));

  collection.InsertMany(documents);

  await
collection.InsertManyAsync(documents);

 

query

  Use the
Find
method to query the collection. The
Find
method returns an
IFindFluent<TDocument, TProjection>
instance that provides a fluent interface for chaining find operation
options.

    var document = collection.Find(new BsonDocument()).FirstOrDefault();
Console.WriteLine(document.ToString());

    var documents = collection.Find(new BsonDocument()).ToList();

  create a
filter to pass to the
Find
method to get a subset of the documents in our collection

    var filter =
Builders<BsonDocument>.Filter.Eq(“i”,
71);

    var document =
collection.Find(filter).First();

 

fields:Many times we
don’t need all the data contained in a document. The
Projection
builder will help build the projection parameter for the find
operation.

  var projection =
Builders<BsonDocument>.Projection.Exclude(“_id”);

  var document = collection.Find(new BsonDocument()).Project(projection).First();

  

update:There are
numerous update
operators
supported by MongoDB.

  The update methods
return an
UpdateResult
which provides information about the operation including the number of
documents modified by the
update.

  var update =
Builders<BsonDocument>.Update.Set(“i”,
110);

 

  var filter =
Builders<BsonDocument>.Filter.Eq(“i”,
10);

  collection.UpdateOne(filter,
update);

  

    

delete:To
delete at most 1 document (may be 0 if none match the filter) use the
DeleteOne
or
DeleteOneAsync
methods:

 

bulk:two
types of bulk operations:

  1. Ordered bulk operations.

    Executes all the operations in order and errors out on the first
error.

  1. Unordered bulk operations.

      Executes all the operations and reports any errors. Unordered bulk
    operations do not guarantee the order of execution.

    var models = new WriteModel[]
    {

    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 4)),
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 5)),
    new InsertOneModel<BsonDocument>(new BsonDocument("_id", 6)),
    new UpdateOneModel<BsonDocument>(
        new BsonDocument("_id", 1), 
        new BsonDocument("$set", new BsonDocument("x", 2))),
    new DeleteOneModel<BsonDocument>(new BsonDocument("_id", 3)),
    new ReplaceOneModel<BsonDocument>(
        new BsonDocument("_id", 3), 
        new BsonDocument("_id", 3).Add("x", 4))
    

    };

// 1. Ordered bulk operation - order of operation is guaranteed
collection.BulkWrite(models);

// 2. Unordered bulk operation - no guarantee of order of operation
collection.BulkWrite(models, new BulkWriteOptions { IsOrdered = false });

 

 

编码教程

 

相关文章