How to select attribute in RavenDB Index in Json-Linq? - linq

In RavenDB my document (ID = 1234) is
"datacontainer": {
"data": [
{
"#idx": "1",
"#idy": "a",
"value": {
"#text": "test 2010"
}
},
{
"#idx": "2",
"#idy": "b",
"value": {
"#text": "test 2011"
}
},
{
"#idx": "3",
"#idy": "c",
"value": {
"#text": "test 2012"
}
}
]
}
I want to create an Index, where I choose my favourite values (for example idx = "2" and idy = "b") and the output will be:
(ID, value_text) = (1234, "test 2011")
Now I can select a single element and check its value in Linq:
where p.datacontainer.data[0]["#idx"] == "2" && p.datacontainer.data[0]["#idy"] == "b"
How can I search the right element in my list?

Luigi,
In RavenDB, you don't search for a list value, you are searching for a document with a given document that matches the query you have.
In your case, what does your entity looks like?

I solved my problem! In RavenDB the index, called "MyIndex", is:
Map:
from p in docs
select new
{ Id = p.id,
M = p.dataApplication.datacontainer.data.Where(x => x["#idx"] == "2").First(x => x["#idy"] == "b").value["#text"]
};
Reduce:
from test in results
group test by new {test.Id, test.M } into g
select new { g.Key.Id, g.Key.M }
Now I can use this Index in my queries, so I will search for a document that contains a particular value, for example:
var results = from p in session.Query<QueryResult>("MyIndex")
where p.M == "test 2011"
select p;
Maybe there is a better solution, but now it works!

Related

Azure CosmoDB - MongoDb - C# - how to increment a value inside an array of Object?

I've this schema for my db:
{
"_id" : "test_schema",
"t" : 5,
"p" : [
{
"id" : "207",
"v" : 4
},
{
"id" : "309",
"v" : 1
}
....
]
}
I'm trying to $inc the v value of p.id equal to "207".
I'm currently able to inc the t value with this code:
var result = collection.UpdateOneAsync(new BsonDocument("_id", "test_schema"}), new BsonDocument("$inc", new BsonDocument("t", 4)), new UpdateOptions() { IsUpsert = true }).Result;
but whe i try to update a value on array nothing happen(even no error!):
var result = collection.UpdateOneAsync(new BsonDocument(new Dictionary<string, object>() { { "_id", "test_schema" }, { "p.id", "207" } }), new BsonDocument("$inc", new BsonDocument("p.v", 4)), new UpdateOptions() { IsUpsert = true }).Result;
Following MongoDB documentation i noticed that "p.v", 4 should be "p.$.v" but in cosmodb raise a not valid $ symbol exception.
Any suggestion?
Cosmos DB doesn't yet support positional operator, it is on the roadmap. The feedback item https://feedback.azure.com/forums/599059-azure-cosmos-db-mongodb-api/suggestions/20091454-positional-array-update-via-query-support is filed to track interest in this feature. Please vote there if you need this support.

How to check an empty JSONArray in swiftyJSON

I have a JSON that have a JSONArray as a value in one of the json inside it. here is the example of it.
[
{
"id": 1,
"symptoms" : [{\"key\":\"sample1\",\"value\":5},{\"key\":\"sample2\",\"value\":5}]
},
{
"id": 2,
"symptoms" : [{\"key\":\"sample3\",\"value\":1}]
},
{ "id": 3,
"symptoms" : []
},
{
"id": 4,
"symptoms": [{\"key\":\"sample4\",\"value\":1}]
}
]
So what I am doing is that I am parsing the inner JSON and place it in a String Array. But whenever I look up to symptoms it skips the empty JSONArray. So whenever i print the String Array it goes like this (with the given sample on top) ["sample1", "sample2", "sample3", "sample4"]. But i want to do is to append an "" to the String Array whenever the JSONArray is empty so it should be like this ["sample1", "sample2", "sample3", "", "sample4"]. Anyone can help me with this? Here is my code
var arrayHolder: [String] = []
var idHolder: [Int] = []
for item in swiftyJSON.arrayValue {
idHolder.append(item["id"].intValue)
//for the inner JSON
let innerJSON = JSON(data: item["symptoms"].dataUsingEncoding(NSUTF8StringEncoding)!)
for symptoms in innerJSON.arrayValue {
arrayHolder.append(symptoms["key"].stringValue)
}
}
print(idHolder) // [1,2,3,4]
print(arrayHolder) // ["sample1","sample2","sample3","sample4"]
Just check if innerJSON is empty:
for item in swiftyJSON.arrayValue {
idHolder.append(item["id"].intValue)
//for the inner JSON
let innerJSON = item["symptoms"].arrayValue // non need to create a new JSON object
if innerJSON.isEmpty {
arrayHolder.append("")
} else {
for symptoms in innerJSON {
arrayHolder.append(symptoms["key"].stringValue)
}
}
}

Removing an elements from basicdblist

Hi i have collection which contains around 200 documents looks like
e.g
"_id": 0,
"name": "Demarcus Audette",
"scores": [
{
"type": "exam",
"score": 30.61740640636871
},
{
"type": "quiz",
"score": 14.23233821353732
},
{
"type": "homework",
"score": 31.41421298576332
},
{
"type": "homework",
"score": 30.09304792394713
}
]
now i wrote code like
DBCursor cursor = collection.find().sort(new BasicDBObject("scores.score":1));
while( cursor.hasNext() )
{
DBobject obj=cursor.next();
BasicDBList list=(BasicDBList) Bobj.get("scores");
// Now here i am getting list of documents which consists of an scores array and i need to remove 3rd elements of it and save collection.... but how to do?
if i use for loop like
for(int i=0;i<list.size();i++)
{
list.remove(2);------ it gives an error here
collection.save(obj);
}
}
Are you sure that you can sort it as 'scores.score'. As 'scores' is a list of objects you cant reference objects inside list using dot notation. Error should be on that line.
Edit:
DBCursor cursor = collection.find();
while ( cursor.hasNext()) {
DBObject dbObject = cursor.next();
BasicDBList dbList = (BasicDBList) (dbObject.get("score"));
//then use java Collections.sort() to sort the List (refer to two methods at the bottom)
dbList.remove(3);
collection.save(dbObject);
}
Use one of the following to sort the DBList
1 . Using Lambda expression
Collections.sort(dbList, (o1, o2) -> Double.compare(((BasicDBObject) o1).getDouble("score"), ((BasicDBObject) o2).getDouble("score")));
or java 7 <
Collections.sort(dbList, new Comparator<Object>() {
public int compare(Object o, Object o2) {
if (((BasicDBObject) o).getDouble("score") >= ((BasicDBObject) o2).getDouble("score")) {
return 1;
}
return -1;
}
});
See this link https://gist.github.com/machadolucas/5188447/raw/e3f5c44c2be756c6087809df63f7ea8f4682ace9/Mongo3_1.java
I`m has been
[some symbol for post this message)))]

jqGrid: Microsoft JScript runtime error: Unable to get value of the property 'integer': object is null or undefined

I get the above exception at this line of code of jqGrid.src.js
fmt = $.jgrid.formatter.integer || {};
I can't for the life of me tell you what that means or why I can't get the damn thing to work. I suspect it has to do with how I am building my json object.
for(int j = rowstart; (j <= rowend && variable.Template.Count > j); j++){
PatientACOModel patMod = variable.Template[j];
var rowData = new{
id = patMod.EncounterId,
cell = new {
MRN = patMod.MRN,
Hospital_Fin = patMod.HospitalFinNumber,
First_Name = patMod.FirstName,
Last_Name = patMod.LastName,
Date_of_birth = patMod.DateOfBirth
}
};
al.Add(rowData);
}
var griddata = new {
total = variable.Template.Count % rows > 0 ? (variable.Template.Count / rows) + 1 : (variable.Template.Count / rows),
page = page,
records = al.Count,
rows = al.ToArray()
};
I have no clue what I am doing wrong? It looks like everything is set up correctly?
UPDATE
This would be the json data that is being sent back to my jqGRid... These are just a small selection of rows, and columns. Am I missing something here?
{"total": 2,
"page": 1,
"records": 15,
"rows": [{
"id": 2148,
"cell": {
"MRN": "840134833",
"Hospital_Fin": "987141516",
"First_Name": "YELLOW",
"Last_Name": "CRAYON",
"Date_of_birth": "\/Date(1253160000000)\/"
}
},
{
"id": 1898,
"cell": {
"MRN": "785528039",
"Hospital_Fin": "6669511596226",
"First_Name": "RAYFIELD",
"Last_Name": "BOYD",
"Date_of_birth": "\/Date(-720298800000)\/"
}
}]}
To eliminate this error, you need to make sure that you are including the localization file
<script src="~/Scripts/i18n/grid.locale-en.js"></script>
before the jqGrid file. That eliminated the problem for me.

having troubles getting !any() query to work with raven db

I am new to RavenDB and it's been frustrating try to get the Any() LINQ query to work correctly. Here is what my document looks like:
{
"Key": "BKey",
"Text": "B Key",
"IsLocal": false,
"Category": null,
"_destroy": false,
"Translations": [
{
"CultureCode": "es-ES",
"Text": null
},
{
"CultureCode": "ja-JP",
"Text": "Hello"
}
]
}
I would expect the following query to give me all entries that don't have translations for "es-ES":
var nonTranslatedEntries =
_docs.Query<ResourceEntry>().Where( e => e.Translations == null || e.Translations.Count == 0 || !e.Translations.Any(t => t.CultureCode == "es-ES" && t.Text != null))
However, this isn't working. It's bringing back the entries even when a translation for the specified CultureCode exists. It works if I have only have one item inside the translations array. But as soon as I have more than one item inside the translations array, then the query stops working.
As an alternative solution, I tried to do the following:
var translatedEntries = from re in _docs.Query<ResourceEntry>()
where re.Translations.Any(t => t.CultureCode == cultureCode && t.Text != null)
select new {Id = re.Id};
var translatedIds = translatedEntries.ToList().Select(e => e.Id).ToList();
var nonTranslatedEntries =
_docs.Query<ResourceEntry>().Where(e => !e.Id.In(translatedEntryIds));
But that just brings back an empty list.
Any help would be very much appreciated.
Thanks,
Nizar
A static index that will get the job done:
public class Resources_ByTranslation :
AbstractIndexCreationTask<ResourceEntry, Resources_ByTranslation.IndexEntry>
{
public class IndexEntry
{
public string Key { get; set; }
public string CultureCodes { get; set; }
}
public Resources_ByTranslation()
{
Map = entries => from entry in entries
select new {
entry.Key,
CultureCodes = entry.Translations
.Where(x => x.Text != null)
.Select(x => x.CultureCode)
};
}
}
Then query with:
var nonTranslatedEntries =
session.Query<Resources_ByTranslation.IndexEntry, Resources_ByTranslation>()
.Where(x => x.CultureCodes != "es-ES")
.As<ResourceEntry>();
Note that the CultureCodes list is being treated as single string. This is due to how then index matching works internally. It's slightly strange, but it does work.
I ended up fixing my issue as follows:
Upon creation of a resource entry, I go ahead and create all the possible translations and set the translation text to null:
{
"Key": "BKey",
"Text": "B Key",
"IsLocal": false,
"Category": null,
"_destroy": false,
"Translations": [
{
"CultureCode": "es-ES",
"Text": null
},
{
"CultureCode": "ja-JP",
"Text": null
}
]
}
I then created the following index:
public class ResourceEntries_ByCultureCodes : AbstractIndexCreationTask<ResourceEntry>
{
public ResourceEntries_ByCultureCodes()
{
Map = entries => from e in entries
select new
{
e.Id,
e.Key,
e.Text,
e.IsLocal,
e.Category,
_ = e.Translations.Select(t => CreateField(t.CultureCode, t.Text != null, false, true))
};
}
}
That gives me a flat record of translations with the value set to 'true' if a translation exists for a that specific culture. For example, I get back something like this:
{
Id,
Key,
Text,
IsLocal,
Category,
es-ES: <true> or <false> depending upon whether Translation.Text != null
ja-JP:<true> or <false> depending upon whether Translation.Text != null
}
I can then do LuceneQuery as follows to get all entries for "es-ES" that have NOT been translated:
_docs.LuceneQuery<ResourceEntry, ResourceEntries_ByCultureCodes>().WhereEquals("es-ES", false);
I wish there were an easier solution, though.

Resources