Skip to content

Commit

Permalink
Added sort, explain, hint and snapshot.
Browse files Browse the repository at this point in the history
  • Loading branch information
samus committed Feb 17, 2010
1 parent 4ce6397 commit 865764c
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 12 deletions.
72 changes: 67 additions & 5 deletions MongoDB.Net-Tests/TestCursor.cs
Expand Up @@ -12,11 +12,6 @@ public class TestCursor
{
Mongo db = new Mongo();

[TestFixtureSetUp]
public void Setup(){
db.Connect();
}

[Test]
public void TestCanReadSmall()
{
Expand Down Expand Up @@ -78,5 +73,72 @@ public void TestCanReadAndKillCursor()
Assert.IsTrue(reads > 0, "No documents were returned.");
Assert.AreEqual(5, reads);
}

[Test]
public void TestSort(){
IMongoCollection sorts = db["tests"]["sorts"];
int[] randoms = new int[]{4,6,8,9,1,3,2,5,7,0};
foreach(int x in randoms){
sorts.Insert(new Document().Append("x", randoms[x]));
}
Assert.AreEqual(randoms.Length, sorts.Count());

int exp = 0;
foreach(Document doc in sorts.FindAll().Sort("x", IndexOrder.Ascending).Documents){
Assert.AreEqual(exp, Convert.ToInt32(doc["x"]));
exp++;
}

exp = 9;
foreach(Document doc in sorts.FindAll().Sort("x", IndexOrder.Descending).Documents){
Assert.AreEqual(exp, Convert.ToInt32(doc["x"]));
exp--;
}
}

[Test]
public void TestExplain(){
Document exp = db["tests"]["reads"].FindAll().Limit(5).Skip(5).Sort("x").Explain();
Assert.IsTrue(exp.Contains("cursor"));
Assert.IsTrue(exp.Contains("n"));
Assert.IsTrue(exp.Contains("nscanned"));
}

[Test]
public void TestHint(){
IMongoCollection reads = db["tests"]["reads"];
Document hint = new Document().Append("x",IndexOrder.Ascending);

Document exp = reads.FindAll().Hint(hint).Explain();
Assert.IsTrue(exp.Contains("$err"), "No error found");

reads.MetaData.CreateIndex("hintindex",hint,false);
exp = reads.FindAll().Hint(hint).Explain();

Assert.IsTrue(exp.Contains("cursor"));
Assert.IsTrue(exp.Contains("n"));
Assert.IsTrue(exp.Contains("nscanned"));
}

[TestFixtureSetUp]
public void Init(){
db.Connect();
cleanDB();
}

[TestFixtureTearDown]
public void Dispose(){
db.Disconnect();
}

protected void cleanDB(){
try{
db["tests"].MetaData.DropCollection("sorts");
}catch(Exception){}
try{
db["tests"]["reads"].MetaData.DropIndex("hintindex");
}catch(Exception){}

}
}
}
71 changes: 70 additions & 1 deletion MongoDBDriver/Cursor.cs
Expand Up @@ -49,6 +49,56 @@ public class Cursor : ICursor {
return this;
}

private QueryOptions options;
public ICursor Options(QueryOptions options){
TryModify();
this.options = options;
return this;
}

#region "Spec Options"
private Document specOpts = new Document();

public ICursor Sort(string field){
return this.Sort(field, IndexOrder.Ascending);
}

public ICursor Sort(string field, IndexOrder order){
return this.Sort(new Document().Append(field, order));
}

public ICursor Sort(Document fields){
TryModify();
AddOrRemoveSpecOpt("$orderby", fields);
return this;
}

public ICursor Hint(Document index){
TryModify();
AddOrRemoveSpecOpt("$hint", index);
return this;
}

public ICursor Snapshot(Document index){
TryModify();
AddOrRemoveSpecOpt("$snapshot", index);
return this;
}

public Document Explain(){
TryModify();
specOpts["$explain"] = true;

IEnumerable<Document> docs = this.Documents;
using((IDisposable)docs){
foreach(Document doc in docs){
return doc;
}
}
throw new InvalidOperationException("Explain failed.");
}

#endregion

private bool modifiable = true;
public bool Modifiable{
Expand Down Expand Up @@ -105,9 +155,11 @@ public class Cursor : ICursor {
private void RetrieveData(){
QueryMessage query = new QueryMessage();
query.FullCollectionName = this.FullCollectionName;
query.Query = this.spec;
query.Query = BuildSpec();
query.NumberToReturn = this.limit;
query.NumberToSkip = this.skip;
query.Options = options;

if(this.fields != null){
query.ReturnFieldSelector = this.fields;
}
Expand Down Expand Up @@ -148,5 +200,22 @@ public class Cursor : ICursor {
if(this.modifiable) return;
throw new InvalidOperationException("Cannot modify a cursor that has already returned documents.");
}

private void AddOrRemoveSpecOpt(string key, Document doc){
if(doc == null){
specOpts.Remove(key);
}else{
specOpts[key] = doc;
}
}

private Document BuildSpec(){
if(this.specOpts.Count == 0) return this.spec;
Document doc = new Document();
this.specOpts.CopyTo(doc);
doc["$query"] = this.spec;
return doc;
}

}
}
13 changes: 13 additions & 0 deletions MongoDBDriver/ICursor.cs
Expand Up @@ -10,7 +10,20 @@ public interface ICursor : IDisposable {
ICursor Limit(int limit);
ICursor Skip(int skip);
ICursor Fields (Document fields);
ICursor Sort(string field);
ICursor Sort(string field, IndexOrder order);
ICursor Sort(Document fields);
ICursor Hint(Document index);
ICursor Snapshot(Document index);
Document Explain();
bool Modifiable { get; }
IEnumerable<Document> Documents { get; }
}

public enum QueryOptions:int{
None = 0,
TailableCursor = 2,
SlaveOK = 4,
NoCursorTimeout = 16
}
}
7 changes: 1 addition & 6 deletions MongoDBDriver/IO/QueryMessage.cs
Expand Up @@ -19,12 +19,7 @@ public class QueryMessage : RequestMessage
// int32 numberToReturn; // number of documents to return in the first OP_REPLY
// BSON query ; // query object. See below for details.
// [ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details.
public enum QueryOptions:int{
None = 0,
TailableCursor = 2,
SlaveOK = 4,
NoCursorTimeout = 16
}


#region "Properties"
private QueryOptions options;
Expand Down

0 comments on commit 865764c

Please sign in to comment.