When I ran into issues with a query to the lbapi, I took a step back a created a very basic app with just the query in it that logged the results.
It looked something like this:
Deft.Chain.pipeline([
function() {
var dd = Ext.create('Deft.Deferred');
Ext.create('Rally.data.lookback.SnapshotStore', {
fetch : ['Parent', 'Feature'],
filters : [{
property : '__At',
value : 'current'
},{
property : '_TypeHierarchy',
value : 'HierarchicalRequirement'
}]
}).load({
params : {
compress : true,
removeUnauthorizedSnapshots : true
},
callback : function(store) {
console.log('store',store);
dd.resolve(store);
}
});
return dd.promise;
}
]).then({
success: function(records) {
console.log('records', records);
}
});
Strangely, if I added a filter like this:
{
property : 'Parent',
operator : '!=',
value : null
}
I got more results. I concluded that the removeUnauthorizedSnapshots must filter the results after they have all been gathered into a page of 20000 results, and thus this would be possible. Can anyone confirm this? Hopefully such confusion can be avoided in the future
You are correct.
removeUnauthorizedSnapshots filters the current pagesize set of results, which means it might actually return a page with 0 results in an extreme case when all results are or were once associated with projects that the user is not allowed to access.
I am not sure about the outcome when you got more results. Additional filter should only limit the number of results further, and I see further reduction when I use a similar code.
But I would like to suggest a syntax change for the filter on Parent property. Nulls are not storied in Lookback API at all, so any != null or == null queries are a little misleading. In your code it works, but in the case of Parent == null, it will return snapshots that don't have a Parent attribute, not just those that have a Parent attribute that is null. You may use exists true instead of != null
filters : [
{
property : 'Parent',
operator : 'exists',
value : true
},{
property : '__At',
value : 'current'
},{
property : '_TypeHierarchy',
value : 'HierarchicalRequirement'
}]
Related
Thank you for first.
MongoDB Version:4.2.11
I have a piece of data like this:
{
"name":...,
...
"administration" : [
{"name":...,"job":...},
{"name":...,"job":...}
],
"shareholder" : [
{"name":...,"proportion":...},
{"name":...,"proportion":...},
]
}
I want to match some specified data through regular expressions:
For a example:
db.collection.aggregate([
{"$match" :
{
"$or" :
[
{"name" : {"$regex": "Keyword"}}
{"administration.name": {"$regex": "Keyword"}},
{"shareholder.name": {"$regex": "Keyword"}},
]
}
},
])
I want to set a flag when the $or operator successfully matches any condition, which is represented by a custom field, for example:{"name" : {"$regex": "Keyword"}}Execute on success:
{"$project" :
{
"_id":false,
"name" : true,
"__regex_type__" : "name"
}
},
{"administration.name" : {"$regex": "Keyword"}}Execute on success:"__regex_type__" : "administration.name"
I try do this:
{"$project" :
{
"_id":false,
"name" : true,
"__regex_type__" :
{
"$switch":
{
"branches":
[
{"case": {"$regexMatch":{"input":"$name","regex": "Keyword"}},"then" : "name"},
{"case": {"$regexMatch":{"input":"$administration.name","regex": "Keyword"}},"then" : "administration.name"},
{"case": {"$regexMatch":{"input":"$shareholder.name","regex": "Keyword"}},"then" : "shareholder.name"},
],
"default" : "Other matches"
}
}
}
},
But $regexMatch cannot match the array,I tried to use $unwind again, but returned the number of many array members, which did not meet my starting point.
I want to implement the same function as mysql this SQL statement in mongodb, like this:
SELECT name,administration.name,shareholder.name,(
CASE
WHEN name REGEXP("Keyword") THEN "name"
WHEN administration.name REGEXP("Keyword") THEN "administration.name"
WHEN shareholder.name REGEXP("Keyword") THEN "shareholder.name"
END
)AS __regex_type__ FROM db.mytable WHERE
name REGEXP("Keyword") OR
shareholder.name REGEXP("Keyword") OR
administration.name REGEXP("Keyword");
Maybe this method is stupid, but I don’t have a better solution.
If you have a better solution, I would appreciate it!!!
Thank you!!!
Since $regexMatch does not handle arrays, use $filter to filter individual array elements with $regexMatch, then use $size to see how many elements matched.
[{"$match"=>{"$or"=>[{"a"=>"test"}, {"arr.a"=>"test"}]}},
{"$project"=>
{"a"=>1,
"arr"=>1,
"src"=>
{"$switch"=>
{"branches"=>
[{"case"=>{"$regexMatch"=>{"input"=>"$a", "regex"=>"test"}},
"then"=>"a"},
{"case"=>
{"$gte"=>
[{"$size"=>
{"$filter"=>
{"input"=>"$arr.a",
"cond"=>
{"$regexMatch"=>{"input"=>"$$this", "regex"=>"test"}}}}},
1]},
"then"=>"arr.a"}],
"default"=>"def"}}}}]
[{"_id"=>BSON::ObjectId('5ffb2df748966813f82f15ad'), "a"=>"test", "src"=>"a"},
{"_id"=>BSON::ObjectId('5ffb2df748966813f82f15ae'),
"arr"=>[{"a"=>"test"}],
"src"=>"arr.a"}]
Here is a store that returns 0 tasks in iteration, even though there are tasks on user stories in iteration 12345. If I use 'HierarchicalRequirement' instead of 'Task' in '_TypeHierarchy', stories are returned. I also tried adding 'Iteration' to the fetch, but it did not help
var snapshotStore = Ext.create('Rally.data.lookback.SnapshotStore', {
autoLoad:true,
fetch : ['Name','_TypeHierarchy'],
filters : [{
property : '__At',
value : 'current'
},
{
property : '_TypeHierarchy',
value : 'Task'
},
{
property : 'Iteration',
value : 12345
}
],
Thank you.
from Rally LBAPI Documentation
The following fields are not available through the Rally Lookback API.
Big/rich text fields (Description, Notes, etc.)
Attachments
Weblink fields
LastBuild, LastRun, LastVerdict on TestCases
Iteration or Release on Tasks
Attributes for all unsupported entities (Workspace, Iteration, Release, Requirement), e.g. Name, EndDate, StartDate on iterations
Probably a lookback newbie question, but how do I return all of the history for stories based on an attribute that gets set later in their history?
Specifically, I want to load all of the history for all stories/defects in my project that have an accepted date in the last two weeks.
The following query (below) doesn't work because it (of course) only returns those history records where accepted date matches the query. What I actually want is all of the history records for any defect/story that is eventually accepted after that date...
filters :
[
{
property: "_TypeHierarchy",
value: { $nin: [ -51009, -51012, -51031, -51078 ] }
},
{
property: "_ProjectHierarchy",
value: this.getContext().getProject().ObjectID
},
{
property: "AcceptedDate",
value: { $gt: Ext.Date.format(twoWeeksBack, 'Y-m-d') }
}
]
Thanks to Nick's help, I divided this into two queries. The first grabs the final history record for stories/defects with an accepted date. I accumulate the object ids from that list, then kick off the second query, which finds the entire history for each object returned from the first query.
Note that I'm caching some variables in the "window" scope - that's my lame workaround to the fact that I can't ever quite figure out the context of "this" when I need it...
window.projectId = this.getContext().getProject().ObjectID;
I also end up flushing window.objectIds (where I store the results from the first query) when I exec the query, so I don't accumulate results across reloads. I'm sure there's a better way to do this, but I struggle with scope in javascript.
filter for first query
filters : [ {
property : "_TypeHierarchy",
value : {
$nin : [ -51009, -51012, -51031, -51078 ]
}
}, {
property : "_ProjectHierarchy",
value : window.projectId
}, {
property : "AcceptedDate",
value : {
$gt : Ext.Date.format(monthBack, 'Y-m-d')
}
}, {
property : "_ValidTo",
value : {
$gt : '3000-01-01'
}
} ]
Filter for second query:
filters : [ {
property : "_TypeHierarchy",
value : {
$nin : [ -51009, -51012, -51031, -51078 ]
}
}, {
property : "_ProjectHierarchy",
value : window.projectId
}, {
property : "ObjectID",
value : {
$in : window.objectIds
}
}, {
property : "c_Kanban",
value : {
$exists : true
}
} ]
Here's an alternative query that will return only the snapshots that represent transition into the Accepted state.
find:{
_TypeHierarchy: { $in : [ -51038, -51006 ] },
_ProjectHierarchy: 999999,
ScheduleState: { $gte: "Accepted" },
"_PreviousValues.ScheduleState": {$lt: "Accepted", $exists: true},
AcceptedDate: { $gte: "2014-02-01TZ" }
}
A second query is still required if you need the full history of the stories/defects. This should at least give you a cleaner initial list. Also note that Project: 999999 limits to the given project, while _ProjectHierarchy finds stories/defects in the child projects, as well.
In case you are interested, the query is similar to scenario #5 in the Lookback API documentation at https://rally1.rallydev.com/analytics/doc/.
If I understand the question, you want to get stories that are currently accepted, but you want that the returned results include snapshots from the time when they were not accepted. Before you write code, you may test an equivalent query in the browser and see if the results look as expected.
Here is an example - you will have to change OIDs.
https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/12352608129/artifact/snapshot/query.js?find={"_ProjectHierarchy":12352608219,"_TypeHierarchy":"HierarchicalRequirement","ScheduleState":"Accepted",_ValidFrom:{$gte: "2013-11-01",$lt: "2014-01-01"}}},sort:[{"ObjectID": 1},{_ValidFrom: 1}]&fields=["Name","ScheduleState","PlanEstimate"]&hydrate=["ScheduleState"]
You are correct that a query like this: find={"AcceptedDate":{$gt:"2014-01-01T00:00:00.000Z"}}
will return one snapshot per story that satisfies it.
https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/12352608129/artifact/snapshot/query.js?find={"AcceptedDate":{$gt:"2014-01-01T00:00:00.000Z"}}&fields=true&start=0&pagesize=1000
but a query like this: find={"ObjectID":{$in:[16483705391,16437964257,14943067452]}}
will return the whole history of the 3 artifacts:
https://rally1.rallydev.com/analytics/v2.0/service/rally/workspace/12352608129/artifact/snapshot/query.js?find={"ObjectID":{$in:[16483705391,16437964257,14943067452]}}&fields=true&start=0&pagesize=1000
To illustrate, here are some numbers: the last query returns 17 results for me. I check each story's revision history, and the number of revisions per story are 5, 5, 7 respectively, sum of which is equal to the total result count returned by the query.
On the other hand the number of stories that meet find={"AcceptedDate":{$gt:"2014-01-01T00:00:00.000Z"}} is 13. And the query based on the accepted date returns 13 results, one snapshot per story.
I would like to link TestCase TestFolder and TestSet.
To do so I start 2 WsapiDataStore queries one on TestFolder and one on TestSet.
Then I parse the data and get the matching TestCase.
Unfortunatly I have not found the way to get more than 200 elements for each queries or to
index the starting index of the queries.
The code I use for a WsapiDataStore query is
_GetTestSetStore : function(TestFolder, container) {
var TestSet_Store = Ext.create('Rally.data.WsapiDataStore', {
model : 'TestSet',
fetch : [ 'FormattedID', 'TestSet' ],
pageSize : PageSize,
autoLoad : true,
listeners : {
load : function(TestSet_Store, TestSet_Data, success) {
if (success) {
container._CleanStore(TestSet_Store, TestSet_Data, TestFolder, container);
} else {
alert('TestSet store query failed');
}
}
}
});
},
Could you help please
Rally.data.wsapi.Store has a config property limit.
You may set limit to Infinity, no quotes.
limit : Number
The total number or records to retrieve with the initial load Defaults to one page worth. To retrieve all records specify Infinity
I'm trying to query for user stories whose release start date is greater than a particular date. Is it possible to do this using the "filters" config rather than querying all stories and then checking manually?
Is this valid? :
Ext.create('Rally.data.WsapiDataStore', {
model: 'UserStory',
context: {
project: '/project/xxxx'
},
autoLoad: true,
fetch: ['Rank', 'FormattedID', 'Release'],
filters: [
{
property: 'Release.ReleaseStartDate',
operator: '>',
value: '2012-10-10'
}
]
});
It doesn't work, just fetches all records.
The code posted above does work. I was actually using a comboBox value in the "value" property. Turns out I didn't convert it to a proper DateTime format and hence the comparison was failing and returning all records.
In my case I had to use Rally.util.DateTime.toIsoString in order to compare the value in the combobox.