Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio_mebibou
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Alexandra Rogova
jio_mebibou
Commits
bf46a5d5
Commit
bf46a5d5
authored
Dec 31, 2013
by
Tristan Cavelier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Queries are now asynchronous
parent
f8c1966d
Changes
9
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
521 additions
and
244 deletions
+521
-244
complex_queries.js
complex_queries.js
+190
-62
src/jio.storage/indexstorage.js
src/jio.storage/indexstorage.js
+23
-22
src/jio.storage/localstorage.js
src/jio.storage/localstorage.js
+21
-20
src/queries/begin.js
src/queries/begin.js
+2
-2
src/queries/core/complexquery.js
src/queries/core/complexquery.js
+73
-14
src/queries/core/query.js
src/queries/core/query.js
+57
-28
src/queries/core/simplequery.js
src/queries/core/simplequery.js
+17
-17
src/queries/core/tool.js
src/queries/core/tool.js
+41
-1
test/queries/tests.js
test/queries/tests.js
+97
-78
No files found.
complex_queries.js
View file @
bf46a5d5
This diff is collapsed.
Click to expand it.
src/jio.storage/indexstorage.js
View file @
bf46a5d5
...
...
@@ -719,7 +719,7 @@
}
}
complex_queries
.
QueryFactory
.
create
(
option
.
query
||
''
).
exec
(
db
,
option
)
;
exec
(
db
,
option
)
.
then
(
function
()
{
for
(
i
=
0
;
i
<
db
.
length
;
i
+=
1
)
{
id
=
db
[
i
].
_id
;
if
(
delete_id
)
{
...
...
@@ -741,6 +741,7 @@
}
}
command
.
success
(
200
,
{
"
data
"
:
{
"
total_rows
"
:
db
.
length
,
"
rows
"
:
db
}});
});
},
function
(
err
)
{
if
(
err
.
status
===
404
)
{
return
command
.
success
(
200
,
{
"
data
"
:
{
"
total_rows
"
:
0
,
"
rows
"
:
[]}});
...
...
src/jio.storage/localstorage.js
View file @
bf46a5d5
...
...
@@ -446,7 +446,7 @@
});
}
complex_queries
.
QueryFactory
.
create
(
options
.
query
||
""
).
exec
(
document_list
,
options
)
;
exec
(
document_list
,
options
)
.
then
(
function
()
{
document_list
=
document_list
.
map
(
function
(
value
)
{
var
o
=
{
"
id
"
:
value
.
_id
,
...
...
@@ -466,6 +466,7 @@
"
total_rows
"
:
document_list
.
length
,
"
rows
"
:
document_list
}});
});
}
};
...
...
src/queries/begin.js
View file @
bf46a5d5
...
...
@@ -19,8 +19,8 @@
return
module
(
exports
);
}
window
.
complex_queries
=
{};
module
(
window
.
complex_queries
);
}([
'
exports
'
],
function
(
to_export
)
{
module
(
window
.
complex_queries
,
RSVP
);
}([
'
exports
'
],
function
(
to_export
,
RSVP
)
{
"
use strict
"
;
/**
...
...
src/queries/core/complexquery.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, query_class_dict: true, inherits: true,
_export
: true, QueryFactory: tru
e */
_export
, QueryFactory, RSVP, sequenc
e */
/**
* The ComplexQuery inherits from Query, and compares one or several metadata
...
...
@@ -56,8 +56,7 @@ ComplexQuery.prototype.toString = function () {
str_list
.
push
(
query
.
toString
());
str_list
.
push
(
this_operator
);
});
str_list
.
pop
();
// remove last operator
str_list
.
push
(
"
)
"
);
str_list
[
str_list
.
length
-
1
]
=
"
)
"
;
// replace last operator
return
str_list
.
join
(
"
"
);
};
...
...
@@ -86,13 +85,41 @@ ComplexQuery.prototype.serialized = function () {
* @return {Boolean} true if all match, false otherwise
*/
ComplexQuery
.
prototype
.
AND
=
function
(
item
,
wildcard_character
)
{
var
j
,
promises
=
[];
for
(
j
=
0
;
j
<
this
.
query_list
.
length
;
j
+=
1
)
{
promises
.
push
(
this
.
query_list
[
j
].
match
(
item
,
wildcard_character
));
}
function
cancel
()
{
var
i
;
for
(
i
=
0
;
i
<
this
.
query_list
.
length
;
i
+=
1
)
{
if
(
!
this
.
query_list
[
i
].
match
(
item
,
wildcard_character
))
{
return
false
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
if
(
typeof
promises
.
cancel
===
'
function
'
)
{
promises
.
cancel
();
}
}
}
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
i
,
count
=
0
;
function
resolver
(
value
)
{
if
(
!
value
)
{
resolve
(
false
);
}
count
+=
1
;
if
(
count
===
promises
.
length
)
{
resolve
(
true
);
}
}
function
rejecter
(
err
)
{
reject
(
err
);
cancel
();
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
resolver
,
rejecter
);
}
return
true
;
},
cancel
)
;
};
/**
...
...
@@ -105,13 +132,41 @@ ComplexQuery.prototype.AND = function (item, wildcard_character) {
* @return {Boolean} true if one match, false otherwise
*/
ComplexQuery
.
prototype
.
OR
=
function
(
item
,
wildcard_character
)
{
var
j
,
promises
=
[];
for
(
j
=
0
;
j
<
this
.
query_list
.
length
;
j
+=
1
)
{
promises
.
push
(
this
.
query_list
[
j
].
match
(
item
,
wildcard_character
));
}
function
cancel
()
{
var
i
;
for
(
i
=
0
;
i
<
this
.
query_list
.
length
;
i
+=
1
)
{
if
(
this
.
query_list
[
i
].
match
(
item
,
wildcard_character
))
{
return
true
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
if
(
typeof
promises
.
cancel
===
'
function
'
)
{
promises
.
cancel
();
}
}
}
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
)
{
var
i
,
count
=
0
;
function
resolver
(
value
)
{
if
(
value
)
{
resolve
(
true
);
}
count
+=
1
;
if
(
count
===
promises
.
length
)
{
resolve
(
false
);
}
}
function
rejecter
(
err
)
{
reject
(
err
);
cancel
();
}
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
then
(
resolver
,
rejecter
);
}
return
false
;
},
cancel
)
;
};
/**
...
...
@@ -124,7 +179,11 @@ ComplexQuery.prototype.OR = function (item, wildcard_character) {
* @return {Boolean} true if one match, false otherwise
*/
ComplexQuery
.
prototype
.
NOT
=
function
(
item
,
wildcard_character
)
{
return
!
this
.
query_list
[
0
].
match
(
item
,
wildcard_character
);
return
sequence
([
function
()
{
return
this
.
query_list
[
0
].
match
(
item
,
wildcard_character
);
},
function
(
answer
)
{
return
!
answer
;
}]);
};
query_class_dict
.
complex
=
ComplexQuery
;
...
...
src/queries/core/query.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global parseStringToObject: true, emptyFunction: true, sortOn: true, limit:
true, select: true, _export: true, stringEscapeRegexpCharacters: true,
deepClone
: tru
e */
deepClone
, RSVP, sequenc
e */
/**
* The query to use to filter a list of objects.
...
...
@@ -64,7 +64,7 @@ function Query() {
* second is the length.
*/
Query
.
prototype
.
exec
=
function
(
item_list
,
option
)
{
var
i
=
0
;
var
i
,
promises
=
[]
;
if
(
!
Array
.
isArray
(
item_list
))
{
throw
new
TypeError
(
"
Query().exec(): Argument 1 is not of type 'array'
"
);
}
...
...
@@ -78,20 +78,34 @@ Query.prototype.exec = function (item_list, option) {
if
(
option
.
wildcard_character
===
undefined
)
{
option
.
wildcard_character
=
'
%
'
;
}
while
(
i
<
item_list
.
length
)
{
if
(
!
item_list
[
i
]
||
!
this
.
match
(
item_list
[
i
],
option
.
wildcard_character
)
)
{
item_list
.
splice
(
i
,
1
);
for
(
i
=
0
;
i
<
item_list
.
length
;
i
+=
1
)
{
if
(
!
item_list
[
i
])
{
promises
.
push
(
RSVP
.
resolve
(
false
)
);
}
else
{
i
+=
1
;
promises
.
push
(
this
.
match
(
item_list
[
i
],
option
.
wildcard_character
));
}
}
return
sequence
([
function
()
{
return
RSVP
.
all
(
promises
);
},
function
(
answers
)
{
var
j
;
for
(
j
=
answers
.
length
-
1
;
j
>=
0
;
j
-=
1
)
{
if
(
!
answers
[
j
])
{
item_list
.
splice
(
j
,
1
);
}
}
if
(
option
.
sort_on
)
{
sortOn
(
option
.
sort_on
,
item_list
);
return
sortOn
(
option
.
sort_on
,
item_list
);
}
},
function
()
{
if
(
option
.
limit
)
{
limit
(
option
.
limit
,
item_list
);
return
limit
(
option
.
limit
,
item_list
);
}
select
(
option
.
select_list
||
[],
item_list
);
},
function
()
{
return
select
(
option
.
select_list
||
[],
item_list
);
},
function
()
{
return
item_list
;
}]);
};
/**
...
...
@@ -103,7 +117,7 @@ Query.prototype.exec = function (item_list, option) {
* @return {Boolean} true if match, false otherwise
*/
Query
.
prototype
.
match
=
function
()
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
};
...
...
@@ -129,24 +143,39 @@ Query.prototype.parse = function (option) {
* @return {Any} The parser result
*/
function
recParse
(
object
,
option
)
{
var
i
,
query
=
object
.
parsed
;
var
query
=
object
.
parsed
;
if
(
query
.
type
===
"
complex
"
)
{
for
(
i
=
0
;
i
<
query
.
query_list
.
length
;
i
+=
1
)
{
return
sequence
([
function
()
{
return
sequence
(
query
.
query_list
.
map
(
function
(
v
,
i
)
{
/*jslint unparam: true */
return
function
()
{
sequence
([
function
()
{
object
.
parsed
=
query
.
query_list
[
i
];
recParse
(
object
,
option
);
return
recParse
(
object
,
option
);
},
function
()
{
query
.
query_list
[
i
]
=
object
.
parsed
;
}
}]);
};
}));
},
function
()
{
object
.
parsed
=
query
;
that
.
onParseComplexQuery
(
object
,
option
);
}
else
if
(
query
.
type
===
"
simple
"
)
{
that
.
onParseSimpleQuery
(
object
,
option
);
return
that
.
onParseComplexQuery
(
object
,
option
);
}]);
}
if
(
query
.
type
===
"
simple
"
)
{
return
that
.
onParseSimpleQuery
(
object
,
option
);
}
}
object
=
{
"
parsed
"
:
JSON
.
parse
(
JSON
.
stringify
(
that
.
serialized
()))};
that
.
onParseStart
(
object
,
option
);
recParse
(
object
,
option
);
that
.
onParseEnd
(
object
,
option
);
return
sequence
([
function
()
{
return
that
.
onParseStart
(
object
,
option
);
},
function
()
{
return
recParse
(
object
,
option
);
},
function
()
{
return
that
.
onParseEnd
(
object
,
option
);
},
function
()
{
return
object
.
parsed
;
}]);
};
/**
...
...
src/queries/core/simplequery.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global Query: true, inherits: true, query_class_dict: true, _export: true,
convertStringToRegExp
: true
*/
convertStringToRegExp
, RSVP
*/
/**
* The SimpleQuery inherits from Query, and compares one metadata value
...
...
@@ -93,12 +93,12 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
}
if
(
comparison_value
===
undefined
)
{
if
(
value
===
undefined
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
if
(
value
===
undefined
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
if
(
convertStringToRegExp
(
...
...
@@ -106,10 +106,10 @@ SimpleQuery.prototype["="] = function (object_value, comparison_value,
wildcard_character
).
test
(
value
.
toString
())
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
}
return
false
;
return
RSVP
.
resolve
(
false
)
;
};
/**
...
...
@@ -134,12 +134,12 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
}
if
(
comparison_value
===
undefined
)
{
if
(
value
===
undefined
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
if
(
value
===
undefined
)
{
return
true
;
return
RSVP
.
resolve
(
true
)
;
}
if
(
convertStringToRegExp
(
...
...
@@ -147,10 +147,10 @@ SimpleQuery.prototype["!="] = function (object_value, comparison_value,
wildcard_character
).
test
(
value
.
toString
())
)
{
return
false
;
return
RSVP
.
resolve
(
false
)
;
}
}
return
true
;
return
RSVP
.
resolve
(
true
)
;
};
/**
...
...
@@ -170,7 +170,7 @@ SimpleQuery.prototype["<"] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
<
comparison_value
;
return
RSVP
.
resolve
(
value
<
comparison_value
)
;
};
/**
...
...
@@ -191,7 +191,7 @@ SimpleQuery.prototype["<="] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
<=
comparison_value
;
return
RSVP
.
resolve
(
value
<=
comparison_value
)
;
};
/**
...
...
@@ -212,7 +212,7 @@ SimpleQuery.prototype[">"] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
>
comparison_value
;
return
RSVP
.
resolve
(
value
>
comparison_value
)
;
};
/**
...
...
@@ -233,7 +233,7 @@ SimpleQuery.prototype[">="] = function (object_value, comparison_value) {
if
(
typeof
value
===
'
object
'
)
{
value
=
value
.
content
;
}
return
value
>=
comparison_value
;
return
RSVP
.
resolve
(
value
>=
comparison_value
)
;
};
query_class_dict
.
simple
=
SimpleQuery
;
...
...
src/queries/core/tool.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global _export
: true
*/
/*global _export
, RSVP
*/
/**
* Escapes regexp special chars from a string.
...
...
@@ -287,3 +287,43 @@ function convertStringToRegExp(string, wildcard_character) {
}
_export
(
'
convertStringToRegExp
'
,
convertStringToRegExp
);
/**
* sequence(thens): Promise
*
* Executes a sequence of *then* callbacks. It acts like
* `smth().then(callback).then(callback)...`. The first callback is called with
* no parameter.
*
* Elements of `thens` array can be a function or an array contaning at most
* three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.
*
* When `cancel()` is executed, each then promises are cancelled at the same
* time.
*
* @param {Array} thens An array of *then* callbacks
* @return {Promise} A new promise
*/
function
sequence
(
thens
)
{
var
promises
=
[];
return
new
RSVP
.
Promise
(
function
(
resolve
,
reject
,
notify
)
{
var
i
;
promises
[
0
]
=
new
RSVP
.
Promise
(
function
(
resolve
)
{
resolve
();
});
for
(
i
=
0
;
i
<
thens
.
length
;
i
+=
1
)
{
if
(
Array
.
isArray
(
thens
[
i
]))
{
promises
[
i
+
1
]
=
promises
[
i
].
then
(
thens
[
i
][
0
],
thens
[
i
][
1
],
thens
[
i
][
2
]);
}
else
{
promises
[
i
+
1
]
=
promises
[
i
].
then
(
thens
[
i
]);
}
}
promises
[
i
].
then
(
resolve
,
reject
,
notify
);
},
function
()
{
var
i
;
for
(
i
=
0
;
i
<
promises
.
length
;
i
+=
1
)
{
promises
[
i
].
cancel
();
}
});
}
test/queries/tests.js
View file @
bf46a5d5
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, exports, require, module, complex_queries, window, test, ok,
deepEqual, s
inon
*/
deepEqual, s
top, start
*/
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
...
...
@@ -23,11 +23,14 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
''
).
exec
(
doc_list
);
stop
();
complex_queries
.
QueryFactory
.
create
(
''
).
exec
(
doc_list
).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
Nothing done on the list
'
);
}).
always
(
start
);
});
test
(
'
Simple Query
'
,
function
()
{
...
...
@@ -35,7 +38,9 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
);
stop
();
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
}
],
'
Document with several identifier should be removed
'
);
...
...
@@ -44,11 +49,15 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
a
"
,
"
b
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
);
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a"
'
).
exec
(
doc_list
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
a
"
,
"
b
"
]}
],
'
Document with several identifier should be kept
'
);
}).
always
(
start
);
});
test
(
'
Complex Query
'
,
function
()
{
...
...
@@ -56,9 +65,10 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
stop
();
complex_queries
.
QueryFactory
.
create
(
'
identifier: "b" AND identifier: "c"
'
).
exec
(
doc_list
)
;
).
exec
(
doc_list
)
.
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
],
'
Document with only one identifier should be removed
'
);
...
...
@@ -67,9 +77,10 @@
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a" OR identifier: "c"
'
).
exec
(
doc_list
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
...
...
@@ -79,12 +90,15 @@
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
o
"
},
{
"
identifier
"
:
[
"
b
"
,
"
c
"
]}
];
complex_queries
.
QueryFactory
.
create
(
return
complex_queries
.
QueryFactory
.
create
(
'
(identifier: "a" OR identifier: "b") AND title: "o"
'
).
exec
(
doc_list
);
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
o
"
}
],
'
Only first document should be kept
'
);
}).
always
(
start
);
});
test
(
'
Wildcard Character
'
,
function
()
{
...
...
@@ -93,9 +107,10 @@
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
stop
();
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a%"
'
).
exec
(
doc_list
,
{
// "wildcard_character": "%" // default
})
;
})
.
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
...
...
@@ -107,9 +122,10 @@
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a%"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
null
});
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "a%"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
null
});
}).
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a%
"
}
],
'
Document "a%" should be kept
'
);
...
...
@@ -119,14 +135,15 @@
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
];
complex_queries
.
QueryFactory
.
create
(
'
identifier: "b"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
"
b
"
})
;
return
complex_queries
.
QueryFactory
.
create
(
'
identifier: "b"
'
).
exec
(
doc_list
,
{
"
wildcard_character
"
:
"
b
"
});
})
.
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
identifier
"
:
"
a
"
},
{
"
identifier
"
:
"
a%
"
},
{
"
identifier
"
:
[
"
ab
"
,
"
b
"
]}
],
'
All documents should be kept
'
);
}).
always
(
start
);
});
test
(
"
Additional Filters
"
,
function
()
{
...
...
@@ -135,14 +152,16 @@
{
"
identifier
"
:
"
a
"
,
"
title
"
:
"
f
"
},
{
"
identifier
"
:
"
b
"
,
"
title
"
:
"
d
"
}
];
stop
();
complex_queries
.
QueryFactory
.
create
(
''
).
exec
(
doc_list
,
{
"
select_list
"
:
[
"
title
"
],
"
limit
"
:
[
2
,
1
],
"
sort_on
"
:
[[
"
identifier
"
,
"
ascending
"
],
[
"
title
"
,
"
descending
"
]]
})
;
})
.
then
(
function
(
doc_list
)
{
deepEqual
(
doc_list
,
[
{
"
title
"
:
"
d
"
}
],
'
The first document should be kept
'
);
}).
always
(
start
);
});
}));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment