Using MongoDB C# driver (http://github.com/samus/mongodb-csharp), seems that I'm unable to get the data by ObjectId. Below the command that I'm using:
var spec = new Document { { "_id", id } };
var doc = mc.FindOne(spec);
I also tried this:
var spec = new Document { { "_id", "ObjectId(\"" + id + "\")" } };
var doc = mc.FindOne(spec);
Both return nothing. Meanwhile, if I query it from the mongo console, it returns the expected result.
My question is, does that driver actually support the lookup by ObjectId?
Thanks..
It does support fetching by object ID. Your id variable should be an Oid. Is it the correct type?
Here is a complete program that will
Connect to Mongo
Insert a document
Fetch the document back using its ID
Print the document's details.
// Connect to Mongo
Mongo db = new Mongo();
db.Connect();
// Insert a test document
var insertDoc = new Document { { "name", "my document" } };
db["database"]["collection"].Insert(insertDoc);
// Extract the ID from the inserted document, stripping the enclosing quotes
string idString = insertDoc["_id"].ToString().Replace("\"", "");
// Get an Oid from the ID string
Oid id = new Oid(idString);
// Create a document with the ID we want to find
var queryDoc = new Document { { "_id", id } };
// Query the db for a document with the required ID
var resultDoc = db["database"]["collection"].FindOne(queryDoc);
db.Disconnect();
// Print the name of the document to prove it worked
Console.WriteLine(resultDoc["name"].ToString());
var spec = new Document { { "_id", ObjectId.Parse(id) } };
var doc = mc.FindOne(spec);
Related
When data from a device goes into the elastic there are duplicates. I like to avoid this duplicates. I'm using a object of IElasticClient, .NET and NEST to put data.
I searched for a method like ElasticClient.SetDocumentId(), but cant find.
_doc doc = (_doc)obj;
HashObject hashObject = new HashObject { DataRecordId = doc.DataRecordId, TimeStamp = doc.Timestamp };
// hashId should be the document ID.
int hashId = hashObject.GetHashCode();
ElasticClient.IndexDocumentAsync(doc);
I would like to update the data set inside the Elastic instead of adding one more same object right now.
Assuming the following set up
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool)
.DefaultIndex("example")
.DefaultTypeName("_doc");
var client = new ElasticClient(settings);
public class HashObject
{
public int DataRecordId { get; set; }
public DateTime TimeStamp { get; set; }
}
If you want to set the Id for a document explicitly on the request, you can do so with
Fluent syntax
var indexResponse = client.Index(new HashObject(), i => i.Id("your_id"));
Object initializer syntax
var indexRequest = new IndexRequest<HashObject>(new HashObject(), id: "your_id");
var indexResponse = client.Index(indexRequest);
both result in a request
PUT http://localhost:9200/example/_doc/your_id
{
"dataRecordId": 0,
"timeStamp": "0001-01-01T00:00:00"
}
As Rob pointed out in the question comments, NEST has a convention whereby it can infer the Id from the document itself, by looking for a property on the CLR POCO named Id. If it finds one, it will use that as the Id for the document. This does mean that an Id value ends up being stored in _source (and indexed, but you can disable this in the mappings), but it is useful because the Id value is automatically associated with the document and used when needed.
If HashObject is updated to have an Id value, now we can just do
Fluent syntax
var indexResponse = client.IndexDocument(new HashObject { Id = 1 });
Object initializer syntax
var indexRequest = new IndexRequest<HashObject>(new HashObject { Id = 1});
var indexResponse = client.Index(indexRequest);
which will send the request
PUT http://localhost:9200/example/_doc/1
{
"id": 1,
"dataRecordId": 0,
"timeStamp": "0001-01-01T00:00:00"
}
If your documents do not have an id field in the _source, you'll need to handle the _id values from the hits metadata from each hit yourself. For example
var searchResponse = client.Search<HashObject>(s => s
.MatchAll()
);
foreach (var hit in searchResponse.Hits)
{
var id = hit.Id;
var document = hit.Source;
// do something with them
}
Thank you very much Russ for this detailed and easy to understand description! :-)
The HashObject should be just a helper to get a unique ID from my real _doc object. Now I add a Id property to my _doc class and the rest I will show with my code below. I get now duplicates any more into the Elastic.
public void Create(object obj)
{
_doc doc = (_doc)obj;
string idAsString = doc.DataRecordId.ToString() + doc.Timestamp.ToString();
int hashId = idAsString.GetHashCode();
doc.Id = hashId;
ElasticClient.IndexDocumentAsync(doc);
}
I'm trying to query a DynamoDB table to find a product based on it's url.
The table has three fields: Title, Description & Url.
var credentials = new BasicAWSCredentials(awsDBLogins.AccessKey, awsDBLogins.SecretKey);
var client = new AmazonDynamoDBClient(credentials, RegionEndpoint.USEast2);
var context = new DynamoDBContext(client);
Table table = Table.LoadTable(client, "Products");
With the above code i'm able to connect to the table. I then execute the below query which does not return any error's however the list of results is empty. I am expecting one result to be returned where the Url matches "test".
var productUrl = "test"
QueryOperationConfig config = new QueryOperationConfig()
{
Filter = new QueryFilter(productUrl, QueryOperator.Equal, "Url"),
AttributesToGet = new List<string>
{ "Title", "Description", "Url" },
ConsistentRead = true,
};
var ProductItem = table.Query(config);
While this does not work in the code, I'm able to find the entry in the database when looking list of item's from the AWS web portal / console so I know that the entry exists.
Am I making a mistake in my filter?
I think the hash key name and value should be reversed. First parameter is the key name and third parameter is the value.
Filter = new QueryFilter("Url", QueryOperator.Equal, productUrl)
So for sqlite I would just do:
var d = new ConnectionHandler();
var writeData =
$"UPDATE `Books` SET Book_Author = #Book_Author WHERE ID = 1";
d.OpenCnx();
using (var cmd = new SQLiteCommand(writeData, d.cnx))
{
cmd.Parameters.AddWithValue("#Book_Author", $"New Book owner");
cmd.ExecuteNonQuery();
}
but for Mongodb for c# what would be the equivalent, or how would I do this
You can get some inspiration for updating a document in the quick-tour documentation provided on the MongoDB site: http://mongodb.github.io/mongo-csharp-driver/2.5/getting_started/quick_tour/
Just look at the Updating Document section.
But to save a click you can use the following code as an inspiration:
// Setup the connection to the database
var client = new MongoClient("mongodb://localhost");
var database = client.GetDatabase("Library");
var collection = database.GetCollection<BsonDocument>("books");
// Create a filter to find the book with ID 1
var filter = Builders<BsonDocument>.Filter.Eq("ID", 1);
var update = Builders<BsonDocument>.Update.Set("Book_Author", "New Book owner");
collection.UpdateOne(filter, update);
I hope this helps.
I am using .Net MongoDB.Driver 2.2.3 and MongoDB 3.2. I want to get the _id of the document I insert or replace with collection.ReplaceOneAsync(), because I use it later on.
However the UpsertedId of the result is null if the operation was an update (it is set, if an insert happened).
What is the best way to determine the _id of the updated document?
var collection = GetMongoDatabase().GetCollection<BsonDocument>("foos");
var document = new BsonDocument
{
{"foo", "new bar"}
};
var result = await collection.ReplaceOneAsync(
Builders<BsonDocument>.Filter.Eq("foo", "bar"),
document,
new UpdateOptions {IsUpsert = true});
// I want to use result.UpsertedId here;
If I take a look at result after an update in Visual Studio's Immediate Window, I see:
?result
{MongoDB.Driver.ReplaceOneResult.Acknowledged}
[MongoDB.Driver.ReplaceOneResult.Acknowledged]: {MongoDB.Driver.ReplaceOneResult.Acknowledged}
IsAcknowledged: true
IsModifiedCountAvailable: true
MatchedCount: 1
ModifiedCount: 1
UpsertedId: null
As far I know ReplaceOneAsync method doesn't return the UpsertedId when the document is replaced, you will see that field with a value when the document is inserted. If you replace an existing document, you can check in your DB that the replacement document is going to have the same _id of the old document:
var collection = GetMongoDatabase().GetCollection<BsonDocument>("foos");
var d=collection.Find<BsonDocument>(Builders<BsonDocument>.Filter.Eq("foo", "bar")).FirstOrDefault();
var id = d["_id"].ToString();//Check your id here
var document = new BsonDocument
{
{"foo", "new bar"}
};
var result = await collection.ReplaceOneAsync(
Builders<BsonDocument>.Filter.Eq("foo", "bar"),
document,
new UpdateOptions {IsUpsert = true});
var d1=collection.Find<BsonDocument>(Builders<BsonDocument>.Filter.Eq("foo", "new bar")).FirstOrDefault();
var id1 = d1["_id"].ToString(); // You will see the same _id
Probably the method you are looking for is FindOneAndReplaceAsync:
var d =collection.FindOneAndReplace<BsonDocument>(Builders<BsonDocument>.Filter.Eq("foo", "new bar"),
document,
new FindOneAndReplaceOptions<BsonDocument, BsonDocument>()
{ IsUpsert=true,
ReturnDocument=ReturnDocument.After
});
var id = d["_id"].ToString();
Per title - I am using the official mongodb driver and I am looking to get all POIs within the given bounding box.
So far I have:
MongoCollection<BsonDocument> collection = _MongoDatabase.GetCollection("pois");
BsonArray lowerLeftDoc = new BsonArray(new[] { lowerLeft.Lon, lowerLeft.Lat});
BsonArray upperRightDoc = new BsonArray(new[] { upperRight.Lon, upperRight.Lat});
BsonDocument locDoc = new BsonDocument
{
{ "$within", new BsonArray(new[] { lowerLeftDoc, upperRightDoc})}
};
BsonDocument queryDoc = new BsonDocument { { "loc", locDoc }};
IList<TrafficUpdate> updates = new List<TrafficUpdate>();
var results = collection.Find(new QueryDocument(queryDoc)).SetLimit(limit);
foreach (BsonDocument t in results)
{
}
Unfortunatelly this doesnt work. I get:
QueryFailure flag was unknown $within type: 0 (response was { "$err" :
"unknown $within type: 0", "code" : 13058 }).
The problem in your code is that you didnt specify which geo operation you wanted to use. You only specified $within but missed where. you must specify $within along with $box (bounding box) , $polygon , $center or $centerSphere / $nearSphere.
This is the correct mongo syntax to run $box queries
> box = [[40.73083, -73.99756], [40.741404, -73.988135]]
> db.places.find({"loc" : {"$within" : {"$box" : box}}})
i am not sure about the c# mongodb syntax. But if you include '$box', it ll work
You could also use the Query builder for this query:
var query = Query.Within("loc", lowerLeft.Lon, lowerLeft.Lat,
upperRight.Lon, upperRight.Lat);
and let the query builder worry about the nitty gritty details of creating a properly formed query.