2

I try to use dictionary in IQueryable but I received run time error ,I know the problem occur because in real time IQueryable is not familiar with that object , I try to convert IQueryable to IEnumerable , but I have problem with the execution of the query. May someone can give me a hint how to execute that function ?

I have the following code:

Dictionary<String, int> coursesType= new Dictionary<string, int>();      
var userQuery = _client.CreateDocumentQuery<ObjectModel.Student>(uriStudentCollection, options).
                    Where(x =>coursesType.ContainsKey(x.MainCourse) 
                    && !x.Courses.ContainsKey(requestCourse)).OrderBy(x => x.Grade).AsDocumentQuery();
                var feedResponse = await userQuery.ExecuteNextAsync<ObjectModel.Student>();

                foreach (var ad in feedResponse.AsEnumerable())
                {
                    results.Add(ad);
                }

UPDATE STATUS: I STILL NOT RECEIVED ANSWER TO MY QUESTION

***UPDATE : I add example of my doc.

    {
    "id": "a5d7f123-80d5-5094-84fb-08c3bc4ccp972",
    "StudentName": "Philip",
"Courses": {
        "Math": {
            "id": "Math",
            "Grade": "98",
            "Place": "NYC"
}
},
"Rank":"AA"
}

UPDATE NUMBER 3

I write the following query :

 SqlQuerySpec q = new SqlQuerySpec()
            {
                QueryText = "SELECT * FROM c WHERE (CONTAINS(LOWER(c[\"courseName\"]),@text) OR CONTAINS(LOWER(c[\"courseDescription\"]),@text) ) AND (udf.CourseContainsKey(c[\"Courses\"],@courseId)=false)",
                Parameters = new SqlParameterCollection()
                {
                    new SqlParameter("@text", text),
                     new SqlParameter("@courseId", courseId)
                }
            };

When I write the query like that, the query work fine, but IF I add the ORDER BY command to the query I received empty set....

"SELECT * FROM c WHERE (CONTAINS(LOWER(c[\"courseName\"]),@text) OR CONTAINS(LOWER(c[\"courseDescription\"]),@text) ) AND (udf.CourseContainsKey(c[\"Courses\"],@courseId)=false) ORDER BY c[\"courseName\"] ASC"

Thanks

Thanks,

MAK

MAK
  • 605
  • 9
  • 19

1 Answers1

2

{"Method 'ContainsKey' is not supported."}

Based on your query, you could use the following code:

var userQuery = _client.CreateDocumentQuery<ObjectModel.Student>(uriStudentCollection, options).
                    Where(x =>coursesType.Keys.Contains(x.MainCourse) 
                    && !x.Courses.Keys.Contains(requestCourse)).OrderBy(x => x.Grade).AsDocumentQuery();

Additionally, if you enable Cross partition query, you would get the following error:

Cross partition query with TOP/ORDER BY or aggregate functions is not supported.

If the filter could not executed on CosmosDB side, I assumed that you need to pull the records from azure side, then filter on your client side. Additionally, here is a similar issue, you could refer to here.

UPDATE:

Sample document:

{
  "id": "1ba6178b-7c22-440a-a4a2-25b4bc636b30",
  "MainCourse": "b",
  "Grade": "B",
  "Courses": {
    "a": "a",
    "b": "b"
  }
}

Query:

SELECT * FROM root WHERE ((root["MainCourse"] IN ("a", "b")) AND (root["Courses"]["a"] != null)) ORDER BY root["Grade"] ASC

Modify your C# code as follows:

!x.Courses.Keys.Contains(requestCourse)

//To

x.Courses[requestCourse]==null

UPDATE2:

For filtering a specific course name not contains within the Courses property, I assumed that you could use User-defined functions, here is the code snippet, you could refer to it:

udf.CourseContainsKey:

function CourseContainsKey (courses,courseName) { 
   if(courses==undefined||courseName==undefined)
   return false;

   return courses.hasOwnProperty(courseName);
}

Test:

enter image description here

UPDATE3:

I have not found any better way to create the query with the UDF, you could follow the code below to create your document query:

var query = $"SELECT* FROM root WHERE (root[\"MainCourse\"] IN({String.Join(",", coursesType.Keys.Select(k=>$"\"{k}\"").ToArray())})) AND udf.CourseContainsKey(root[\"Courses\"],\"{requestCourse}\")=false ORDER BY root[\"Grade\"] ASC";
var items=client.CreateDocumentQuery<CourseSample>(UriFactory.CreateDocumentCollectionUri(DatabaseId, DocumentCollectionId), sqlExpression:query).ToList();
Bruce Chen
  • 18,207
  • 2
  • 21
  • 35
  • Hii, Thank you for your answer , it's solved part of the problem, I have two question 1.When we use the Keys.Contains , we actually hurt the performance if we compare it to ContainsKey , I see the query is equal to IN (\"Collection\", \"mat\", \"physic\"). 2. The !x.Courses.Keys.Contains(requestCourse) is not work it's return an empty set (I sure that query is not empty) , what is the different ? the query is ARRAY_CONTAINS(root[\"Courses\"][\"Keys\"], \"philo\") – MAK Sep 28 '17 at 18:40
  • I checked the query and updated my answer for modification. – Bruce Chen Sep 29 '17 at 09:24
  • Hii, it's still not solve the problem it's equal to (NOT (root[\"Courses\"][\"phil\"] != null) and it's return empty set :-( – MAK Sep 29 '17 at 13:38
  • Hi, it's still not working , I received empty set,the query translate to AND (root[\"Courses\"][\"phil\"] = null) ,( I sure the query is not empty set). – MAK Oct 06 '17 at 11:38
  • x.Courses[requestCourse]==null not solved the problem , I received empty set , the linq translate into SQL query :root[\"Courses\"][\"philo\"] = null – MAK Nov 04 '17 at 22:13
  • Could you show your document sample? I tested the query against my document, you could provide your document sample, I would check it on my side. – Bruce Chen Nov 09 '17 at 01:34
  • Based on your doc sample, I did some test and updated my answer, you could refer to it. – Bruce Chen Nov 13 '17 at 03:12
  • thank you for your answer , can you please explain how I can use it via c# code? If I have code that need to find if course belong to my main subject and the student is not taken that course (like in my origin question ) , thanks a lot! – MAK Nov 13 '17 at 13:09
  • I just updated my answer with the code snippet, you could refer to it. – Bruce Chen Nov 14 '17 at 09:33