Custom serializers and deserializers in LiteDB v5.0.9 - litedb

The release notes for LiteDB 5.0.9 says, "Custom serializers and deserializers can now be used even with basic BSON types. This is useful if you don't want to lose precision when storing DateTime." But there doesn't appear to be any documentation describing how to do this. Can someone point me to it or provide an example?
Thanks

DateTime precision seems to be a common issue with LiteDB. Issue 1765 provides the following solution:
var mapper = new BsonMapper();
mapper.RegisterType<DateTime>(
value => value.ToString("o", CultureInfo.InvariantCulture),
bson => DateTime.ParseExact(bson, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind));
mapper.RegisterType<DateTimeOffset>(
value => value.ToString("o", CultureInfo.InvariantCulture),
bson => DateTimeOffset.ParseExact(bson, "o", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind));
using (var db = new LiteDatabase("instance.db", mapper))
{
...
}

Related

MongoDB append simple java data types as 'Object' to a document fields

I'm just starting with MongoDB.
I have a Map<String, Object> that contains several data types as a values. For example:
{ "price":235837210, "name":"hello", "position":1, "onAir":false, ... }
Now I'm trying to append these elements to a MongoDB Document as follows:
for (Map.Entry<String, Object> entry : map.entrySet()) {
document.append(entry.getKey(), entry.getValue());
}
As a result I get the following exception:
org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class [Ljava.lang.Object;.
The use case is much more complicated, but the question is if I can do this in any way in order to avoid specific casting. Something like:
document.append("price", (long)map.get("price"));
Thanks,
Joan.
Sorry, it was a problem with using Object[] instead of ArrayList.

Scala, Quill - how to compare values with case-insensitive?

I created a quill query, which should find some data in database by given parameter:
val toFind = "SomeName"
val query = query.find(value => infix"$value = ${lift(toFind)}".as[Boolean])
It works fine when for example I have data in database "SomeName", but if I want to have same results by passing there "somename" I found nothing. The problem is with data case-sensitive.
Is it possible to always find values with case-insensitive way? In quill docs I have not found anything about it.
Ok, I found a solution. It is enough to add LOWER() sql function to infix:
val query = query.find(value => infix"LOWER($value) = ${lift(toFind.toLowerCase)}".as[Boolean])

Spring Data MongoDB - Is there a way to have an implicit timestamp?

Using my MongoDB and Spring Data MongoDB I am currently looking for a timestamp to be visible in the collection documents.
For now the document looks like this:
{
"_id":"f84fd693-e04b-4acb-9390-32ee755c1506",
"name":"Herbert",
"age":{"$numberInt":"21"},
"_class":"com.alemannigame.backend.domain.Character"
}
However I'd like to have a "timestamp": "1988-03-12T02:30:12+00:00" (example format) in it as well. Is there a way to do so without having to write logic in a Service to actually add a timestamp manually?
I thought about something like:
#Document(withTimestamp: true) // this
data class Character(
#Id
val id: String,
val name: String,
val age: Int
)
Could not find anything similar in the interwebs! Nifty solutions are welcome!
So I found something out about Lifecycle Events for Spring Data MongoDB (https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.aggregation).
This gave me several interceptors before a document is saved to MongoDB.
It's very straight forward to use. I chose the onBeforeConvert hook so I can manipulate my model before it is being saved.
As you can see I added the timestamp of the event to my source instance. I like Unix timestamps and since the event object already has that ready I reused it.
#Component
class MongoSaveInterceptor : AbstractMongoEventListener<Character>() {
override fun onBeforeConvert(event: BeforeConvertEvent<Character>) {
val source = event.source
source.timestamp = event.timestamp
}
}
When using MongoDB's implicit ObjectId (which I do not - I use an own UUID id) I think that event.timestamp is used here.

Index hint with mongodb csharp

I am migrating from the mongodb csharp driver 1.10.0 to 2.0.0.
One of the collection I am using is very big and has to fulfill many queries with different filter attributes. That is why I was relying on some index hint statements. With the v1.10 driver it looks like
myCollection.Find(query).SetHint("myIndexName");
I searched the v2 driver api but this hint method seems to be completly removed in the v2 driver. Is there an alternative? How should I do index hints with the v2 driver?
Note: The Solutions provided works for latest mongodb csharp drivers as well
You can use the FindOptions.Modifiers property.
var modifiers = new BsonDocument("$hint", "myIndexName");
await myCollection.Find(query, new FindOptions { Modifiers = modifiers }).ToListAsync();
May I ask why you are using the hint? Was the server consistently choosing the wrong index? You shouldn't need to do this except in exceptional cases.
Craig
Ideally, try to make the query in a way that mongodb optimizer can use the index automatically.
If you are using FindAsync then you will have a property named Hint. Use it like this:
If you have index named "myIndexName" which you want your query should use forcefully, then use like this:.
BsonString bsonString = new BsonString("myIndexName");
cursor = await collection.FindAsync(y => y.Population > 400000000,
new FindOptions<Person, Person>()
{
BatchSize = 200,
NoCursorTimeout = true,
AllowPartialResults = true,
Projection = "{'_id':1,'Name':1,'Population':1}"
Hint = bsonString.AsBsonValue,
}).ConfigureAwait(false);
You can fine BsonString class in MongoDB.Bson
With agregate you can force indice like this:
BsonString bsonString = new BsonString("ix_indice");
var query = this.collection.Aggregate(new AggregateOptions() { Hint = bsonString }).Match(new BsonDocument {..});
If you are using the Linq IQueryable, you can specify the hint (and other options) like this:
BsonDocument hint = new BsonDocument("myFieldName", 1);
// or
BsonDocument hint = new BsonString("myIndexName");
await collection.AsQueryable(new AggregateOptions { Hint = hint })
myFieldName can also reference a complex field, e.g. Metadata.FileName
myIndexName is the name of an index. I prefer to reference the field (first option) directly, instead of an index, for simple cases.

Perl mongo $coll->find_one({"_id" => "xxxx"}) method not function as expected

I know another users had asked this question. I test and it doesn't work. I find this problem when use the $coll->remove({"_id" => "xxxx"}) not hehaviour as expected.
Following is the summary of my test:
print Dumper $db->posts->find_one({"_id" => "4d92740b2239007c16130000"});
$VAR1= undef;
print Dumper $db->posts->find_one({"_id" => $conn->oid("4d92740b2239007c16130000")});
print out a document with _id => "4d9274032e62007c16110000"
Does the autogenerated _id object can be used to manage documents?
http://www.mongodb.org/display/DOCS/Removing
db.things.remove({_id: myobject._id});
The _id is not a string. It's a 12 byte binary value stored as a BSON object:
http://www.mongodb.org/display/DOCS/Object+IDs
You can remove by the _id but you can't use the 24 digit hex string representation. This is exactly the same behavior as find_one() which you have already discovered.
$coll->remove({"_id" => $myObject->{_id}});
There is a clear distinction between an objectid and its string representation. Why should the first find_one() with the string representation return a result if you are actually using an ObjectId as _id here? So the behavior is completely correct - independent of the driver used. If you introduce your string object ids for whatever reason then you will be able to search by string. As long as the driver injects decicated objectid (which aren't strings) you will have to search by them and not by their string representation.