0

I have the collection that contains images and DCT hash for their. How I can select only similar images using Similarity(long hash, long hashOther) method in LINQ where clause.
This query is not work:

var results = imageCollection
.AsQueryable()
.Where(x=>ImageHash.Similarity(x.Hash, hash) >= 50)
.ToList();

Serialization error occurs.

Thanks!

Nodir
  • 359
  • 1
  • 3
  • 17
  • May be implementing Similarity(long Hash) method in POCO entity object resolve this problem? `.Where(x=>x.Similarity(hash) >= 50).ToList();` – Nodir Jan 21 '14 at 22:25

2 Answers2

1

Keep in mind that any LINQ query you write against MongoDB must ultimately be translated into an equivalent query in the MongoDB query language. The LINQ query you wrote can't be translated to a raw MongoDB query because this part:

.Where(x=>ImageHash.Similarity(x.Hash, hash) >= 50)

has no equivalent in the MongoDB query language.

What you will have to do is fetch all the Image _id and Hash values client side and run your Similarity criteria client side. Once you have the _id values of all the images that are similar enough you can fetch the images themselves.

Hopefully your query will also include other criteria so that only a subset of the images need to be run through the Similarity criteria client side.

It would look more or less like this:

var matchingIds = collection.FindAllAs<BsonDocument>
    .SetFields("_id", "Hash")
    .AsEnumerable() // force client side evaluation of the rest of the query
    .Where(x => ImageHash.Similarity(x["Hash"].AsByteArray, hash) > 50))
    .Select(x => x["_id"]);
var query = Query.In("_id", matchingIds);
var matchingImages = collection.Find(query);
foreach (var image in matchingImages)
{
    // process matching image
}
Robert Stam
  • 12,039
  • 2
  • 39
  • 36
0

As you say in your comment, have you tried a POCO class?

public class MyImage
{
 [BsonId]
 public ObjectId id {get;set;}    
 public string Hash {get;set;}

}

var results = imageCollection
 .AsQueryable(MyImage)
.Where(x=>ImageHash.Similarity(x.Hash, hash) >= 50)
.ToList();
rubenfa
  • 831
  • 1
  • 7
  • 23
  • But I does not want implement any methods in POCO class. It is not the best solution. – Nodir Jan 21 '14 at 22:34
  • If I'm not wrong MongoDB C# driver still does not support LINQ queries against . So you should use properties and classes. But according to [this Jira](https://jira.mongodb.org/browse/CSHARP-633) it is planned to be released on next version of C# driver. – rubenfa Jan 21 '14 at 22:56
  • Can I rewrite comparison method in javascript and use it by MapReduce? – Nodir Jan 22 '14 at 07:12
  • Could be an option. [Here](http://odetocode.com/blogs/scott/archive/2012/03/19/a-simple-mapreduce-with-mongodb-and-c.aspx) you have a MapReduce example. Other option could be to avoid LINQ. Yo can carry out queries with Query Builder. But the main problem is that you need to use a function over a field value. – rubenfa Jan 22 '14 at 10:32