【问题标题】:Pouch DB data is not inserted in sorted orderPouch DB 数据未按排序顺序插入
【发布时间】:2022-02-08 23:56:15
【问题描述】:

我正在研究电子和 pouchdb 的小型形式。

将数据插入数据库时​​,直到第 9 个文档完美插入,但在第 10 个文档时,它插入到文档的第二个位置,而不是插入到最后一个位置

在插入第 10 个文档之前

{
  "total_rows": 9,
  "offset": 0,
    "rows": [
    { "id": "1", "key": "1", "value": {...} },
    { "id": "2", "key": "2", "value": {...} },   
    { "id": "3", "key": "3", "value": {...} },
    { "id": "4", "key": "4", "value": {...} }    
    { "id": "5", "key": "5", "value": {...} },
    { "id": "6", "key": "6", "value": {...} },   
    { "id": "7", "key": "7", "value": {...} },
    { "id": "8", "key": "8", "value": {...} },
    { "id": "9", "key": "9", "value": {...} }
  ]
}

插入第 10 个文档后

{
  "total_rows": 10,
  "offset": 0,
    "rows": [
    { "id": "1", "key": "1", "value": {...} },
    { "id": "10", "key": "10", "value": {...} },
    { "id": "2", "key": "2", "value": {...} },   
    { "id": "3", "key": "3", "value": {...} },
    { "id": "4", "key": "4", "value": {...} }    
    { "id": "5", "key": "5", "value": {...} },
    { "id": "6", "key": "6", "value": {...} },   
    { "id": "7", "key": "7", "value": {...} },
    { "id": "8", "key": "8", "value": {...} },
    { "id": "9", "key": "9", "value": {...} }
  ]
}

这里附上js代码

// form submit
const form = document.getElementById("form1");
form.addEventListener("submit", dbsubmit);

function dbsubmit(e) {
   e.preventDefault();
   //   getting values from form
   var Sno = document.getElementById("number").value
   var date = document.getElementById("date").value;
   var Time = document.getElementById("time").value;
   var Trip = document.querySelector('input[name="Trip"]:checked').value;
   var TripType = document.querySelector('input[name="Type"]:checked').value;
 
 // assigning form values to db table names
  var doc = {
    _id: Sno,
    Date: date,
    time: Time,
    trip: Trip,
    triptype: TripType,
  };

   // inserting to db
  db.put(doc, function(err, response) {
    if (err) {
      return console.log(err);
    } else {
      console.log("Document created Successfully", response);
    }
  });
}

插入到第九个第 9 个文档它完全插入,但是当插入第 10 个文档时它插入到第二个位置。

文档应该按id排序,想用它在另一个页面查看。

我调试了但找不到解决方案,谁能帮我解决一下?

谢谢

【问题讨论】:

  • 尽量避免发布图片。除了死链接等,它还可以防止有视力障碍的人参与和分享他们的知识。

标签: javascript couchdb pouchdb


【解决方案1】:

您对文档插入有一个错误的概念,无论是插入的顺序与时间有关,这在诸如 MS/SQL 之类的 RDBMS 中是可以预期的,还是认为数字值的字符串表示应该根据隐含的数值排序(这将是 db 的疯狂猜测)。

正如明确指出的 hereherehere,以及 CouchDB 文档中指定的 3.2.2.5. Collation Specification

字符串的比较是使用 ICU 完成的,它实现了 Unicode Collat​​ion Algorithm,对键进行字典排序。如果您期望 ASCII 排序,这可能会产生令人惊讶的结果。

文档不按插入顺序返回,而是根据应用于文档ID的排序规则返回,文档ID是字符串

例如,您期望这种排序:

row # id
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10

但不符合排序规则,这会产生

row # id
0 1
1 10
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9

再次强调,插入顺序(更不用说隐含的数值)会影响结果的顺序。从 RDBMS 的角度来看,将 _all_docs 结果按_id 上的索引排序是有帮助的,该索引根据排序规则排序(同样,对于字符串,因为所有_ids 都是字符串类型)。

下面的 sn-p 通过创建 100 个 id 从 1 到 100 的文档来演示这一点。

// generate canned test documents with doc _id's in the range 1 to 100.
function getDocsToInstall() {
  let docs = [];
  for (let i = 1; i < 101; i++) {
    //  _id must be a string type because that's the way it is, period.
    docs.push({
      _id: i.toString()
    });
  }
  return docs;
}

let db;

// init db instance
async function initDb() {

  db = new PouchDB('test', {
    adapter: 'memory'
  });
  await db.bulkDocs(getDocsToInstall());
}

initDb().then(async() => {
  let options = {
    limit: 25,
    include_docs: false,
    reduce: false
  };

  const result = await db.allDocs(options);
  showResult(result);

});


function gel(id) {
  return document.getElementById(id);
}

function cel(name) {
  return document.createElement(name);
}

function addColumn(tr, value) {
  const td = cel('td');
  td.innerText = value;
  tr.append(td);
}

function addRow(row, index) {
  const tr = cel('tr');
  [index, row.id].forEach(value => addColumn(tr, value));
  gel('table').append(tr);
}

function showResult(result) {
  const table = gel('table');
  result.rows.forEach((row, index) => {
    addRow(row, index);
  });
}
th,
td {
  padding: .5em;
  text-align: left;
  min-width: 4em;
}

table {
  border-collapse: collapse;
}
<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>
<table id="table" border="1">
  <tr>
    <th>row #</th>
    <th>id</th>

  </tr>
</table>

sn-p 必须得到的结论是返回的前 3 个文档是

row # id
0 1
1 10
2 100

作为janl pointed out here,如果您需要按照数字顺序访问文档,那么创建view 是一个不错的选择,下面的sn-p 演示了这一点。

sn-p 并排显示来自 _all_docs 和 my_index 视图的结果。

// generate canned test documents with doc _id's in the range 1 to 100.
function getDocsToInstall() {
  let docs = [];
  for (let i = 1; i < 101; i++) {
    //  _id must be a string type because that's the way it is, period.
    docs.push({
      _id: i.toString()
    });
  }
  // add a design doc/view for numerically ordered documents
  docs.push({
    _id: '_design/my_ddoc',
    views: {
      my_index: {
        map: function(doc) {
          emit(Number(doc._id));
        }.toString()
      }
    }
  })
  return docs;
}

let db;

// init db instance
async function initDb() {

  db = new PouchDB('test', {
    adapter: 'memory'
  });
  await db.bulkDocs(getDocsToInstall());
}

initDb().then(async() => {
  let options = {
    limit: 25,
    include_docs: false,
    reduce: false
  };

  const allDocs = await db.allDocs(options);
  const view = await db.query('my_ddoc/my_index');
  showResult(allDocs, view);

});


function gel(id) {
  return document.getElementById(id);
}

function cel(name) {
  return document.createElement(name);
}

function addColumn(tr, value) {
  const td = cel('td');
  td.innerText = value;
  tr.append(td);
}

function addRow(index, allDocs, view) {
  const tr = cel('tr');
  [index, allDocs.rows[index].key, view.rows[index].key].forEach(value => addColumn(tr, value));
  gel('table').append(tr);
}
// show allDocs and view results side by side
function showResult(allDocs, view) {
  const table = gel('table');
  for (let i = 0; i < allDocs.rows.length; i++) {
    addRow(i, allDocs, view);
  };
}
th,
td {
  padding: .5em;
  text-align: left;
  min-width: 4em;
}

table {
  border-collapse: collapse;
}
<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>
<table id="table" border="1">
  <tr>
    <th>row #</th>
    <th>_all_docs key</th>
    <th>my_index key</th>
  </tr>
</table>

请注意,对于 _all_docs,keyid 是文档 _id。重要的是要了解 _all_docs 实际上是一个内置视图,它解释了为什么 keyid 出现在 _all_docs 结果中。

如果实际上您希望文档按时间排序,则将创建时间戳添加到文档并基于该时间戳构建视图,例如如果 creationTime 是一个整数,表示 Unix 纪元中的时间点(毫秒),则 map 函数可能如下所示。

function(doc) {
   emit(doc.creationTime);
}

【讨论】:

  • 感谢您完整解释的回答,如果我们想按排序顺序使用数据库数据,我们想创建一个新数据库并推送使用视图排序的文档,我们应该正确使用它
  • 将视图的结果推送到另一个数据库将是一种浪费和超级复杂性,因为另一个数据库上的 _all_docs 结果将与源数据库相同,因为再次,整理规则。什么也得不到。只需使用视图 - 这是该功能存在的一个示例。
  • 在表单 ui 图像中,我通过获取最后一个 id 并递增 1 并在每次重新加载时附加到下拉列表来更新 sno 下拉列表,这是否也可以通过视图来完成?
  • 可以通过 sort order = descending 和 limit = 1 查询数值视图,得到最大值。如果多个客户端可以同时使用该表单,则存在两个客户端可能发布相同 ID 的风险,这将导致 409 Conflict。这将需要一个复杂的工作流程来完成这项工作。一般来说,增量id很难实现,如果允许离线创建文档,实现起来非常困难。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
  • 1970-01-01
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多