CouchDB显示不同的值 [英] CouchDB display distinct values
问题描述
我有一个如下文件,
{
"id": "7d9fdc2f4846544d62da3421bf011b31",
"al": [
{ "id16": "0x1d42",
"pos": {
"x": 10.32,
"y": 11.13,
"z": 1.22
},
"resultTime": "2020-06-01T20:45:34.976Z"
},
{ "id16": "0x1342",
"pos": {
"x": 0.32,
"y": 1.13,
"z": 13.22
},
"resultTime": "2021-06-01T20:45:34.976Z"
}
.
.
.
],
"Timestamp": 272179,
"Oid": "Onion1",
}
和设计文档如下所示
{
"id": "_design/GetALwithAnchorID",
"key": "_design/GetALwithAnchorID",
"value": {
"rev": "32-6db6c4e105336d47a6c8e7e8458ee345"
},
"doc": {
"_id": "_design/GetALwithAnchorID",
"_rev": "32-6db6c4e105336d47a6c8e7e8458ee345",
"views": {
"GetALwithAnchorID": {
"map": "function (doc) {\n\n for (var i=0; i<doc.al.length; i++) { \n emit(doc.al[i].id16, doc.al[i].pos);\n }\n \n}\n\n",
"reduce": "_approx_count_distinct"
}
},
"language": "javascript"
}
}
当我查询类似视图时
我得到的结果如下
{"rows":[
{"key":"0x1d42","value":1}
]}
但是我想要id16和id16的pos的不同值.并按时间对这些不同的值进行排序,并在Iquery时显示pos的值而不是"value":1
?
But I want distinct values of id16 and pos of id16. and to sort these distinct values by time and display the values of pos instead of "value":1
when Iquery?
先谢谢您
推荐答案
OK so not quite the same as this similar answer. Anyone coming across this Q/A, I recommend reading over that answer.
为您的给定文档结构考虑以下 emit
:
Consider the following emit
for your given doc structure:
doc.al.forEach(e => emit(
[e.pos.x, e.pos.y, e.pos.z, e.resultTime], // key
[e.id16, e.pos, e.resultTime]) // value
));
emit
的复杂键在索引中可视化(通常不是逐字显示):
The emit
's complex key visualized in the index (loosely not verbatim):
[-3,-2,-1,"2017-10-28T22:56:58.852Z"]
[-3,-2,-1,"2019-01-23T03:33:20.958Z"] **
. . .
[0,0,0,"2016-05-27T01:38:36.305Z"]
[0,0,0,"2016-12-27T05:17:02.255Z"] **
. . .
[1,2,3,"2016-11-14T17:31:59.468Z"]
[1,2,3,"2017-07-17T07:52:38.180Z"] **
每个**是 pos
组中的最后一项,而显着的是最新 resultTime
.全部归功于CouchDB的排序规则.
Where each ** the last item in the pos
group and significantly the most recent resultTime
. All due to CouchDB's collation.
Working with CouchDB demands understanding the B-tree, and it's documentation has a great rundown of it in its Reduce/Rereduce documentation.
现在考虑使用此 reduce
函数:
function(keys,values,rereduce) {
return values[0];
}
看起来并不令人印象深刻,但请进一步考虑使用以下参数调用视图:
It doesn't look terribly impressive, but further consider calling the view with these parameters:
{
reduce: true,
group_level: 1,
descending: true
}
通过使用 descending
反转索引扫描的顺序,可以保证 reduce
函数返回关于 resultTime
的最新行任何给定的 pos
组.
By reversing the order of the index scan with descending
the reduce
function is guaranteed to return the most recent row with respect to resultTime
of any given pos
group.
这是一个使用pouchDB的简单演示.它生成6个具有随机 pos
.看看设计文档.
Here's a simple demo using pouchDB. It generates 6 documents with random resultTime
's and randomly selects pos
from a pool of 3. Have a look at the design doc.
async function showReduceDocs(view) {
let result = await db.query(view, {
reduce: true,
group_level: 1,
descending: true
});
// show
debugger;
gel('view_reduce').innerText = result.rows.map(row => `${JSON.stringify(row.value)}`.split(',').join(', ')).join('\n');
return result;
}
async function showViewDocs(view) {
let result = await db.query(view, {
reduce: false,
include_docs: false
});
//show
gel('view_docs').innerText = result.rows.map(row => JSON.stringify(row.key))
.join('\n');
}
function getDocsToInstall(count) {
// design document
const ddoc = {
"_id": "_design/SO-66231293",
"views": {
"id16": {
"map": `function (doc) {
doc.al.forEach((e) => emit([e.pos.x, e.pos.y, e.pos.z, e.resultTime],[e.id16, e.pos, e.resultTime]));
}`,
"reduce": `function(keys,values,rereduce) {
return values[0];
}`
}
}
};
// create a set of random documents.
let docs = new Array(count);
let docId = 65;
const posSeed = [{
x: 0,
y: 0,
z: 0
},
{
x: 1,
y: 2,
z: 3
},
{
x: -3,
y: -2,
z: -1
}
];
const dateSeed = [new Date(2000, 0, 1), new Date(), 0, 24];
while (count--) {
let n = 6;
let doc = {
_id: String.fromCharCode(docId++),
al: new Array(n)
};
while (n-- > 0) {
doc.al[n] = {
"id16": "0x000" + n,
"pos": posSeed[Math.floor(Math.random() * 100) % 3],
"resultTime": randomDate(...dateSeed).toISOString()
};
}
docs[count] = doc;
}
docs.push(ddoc);
return docs;
}
const db = new PouchDB('SO-66231293', {
adapter: 'memory'
});
(async() => {
// install docs and show view in various forms.
await db.bulkDocs(getDocsToInstall(6));
gel('content').classList.remove('hide')
showReduceDocs('SO-66231293/id16');
showViewDocs('SO-66231293/id16');
})();
const gel = id => document.getElementById(id);
/*
https://stackoverflow.com/questions/31378526/generate-random-date-between-two-dates-and-times-in-javascript/31379050#31379050
*/
function randomDate(start, end, startHour, endHour) {
var date = new Date(+start + Math.random() * (end - start));
var hour = startHour + Math.random() * (endHour - startHour) | 0;
date.setHours(hour);
return date;
}
<script src="https://cdn.jsdelivr.net/npm/pouchdb@7.1.1/dist/pouchdb.min.js"></script>
<script src="https://github.com/pouchdb/pouchdb/releases/download/7.1.1/pouchdb.memory.min.js"></script>
<div id='content' class='hide'>
<div>View: reduce</div>
<pre id='view_reduce'></pre>
<hr/>
<div>View: complex key</div>
<pre id='view_docs'></pre>
</div>
修改根据OP的评论修改了演示代码段.
Edit Amended the demo snippet according to OP's comments.
这篇关于CouchDB显示不同的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!